ания (что вряд ли приемлимо), множественное
наследование только от специальных абстрактных классов-интерфейсов (такой
подход принят в Java), наследование только от неродственных
классов-родителей, и, наконец, наследование без каких-либо ограничений.
Есть достаточно много неясных вопросов, связанных с аспектами защиты
содержимого классов. В настоящей редакции языка принят намного более
либеральный подход к этому вопросу, чем в C++ и Java. Язык допускает
разнообразные механизмы инициализации экземпляра класса (экземпляром,
списком компонент, конструктором и, наконец, всегда доступна автоматическая
неявная инициализация). Как правило, объекты всегда инициализируются неким
"разумным" образом, однако может возникнуть потребность и в классах --
"черных ящиках", инициализация которых происходит исключительно через
посредство конструкторов. С самой семантикой конструкторов также есть
некоторые неясности.
Наконец, дискуссионным является вопрос о том, какие средства должны
быть встроены в язык, а какие -- реализованы в стандартных библиотеках.
Например, обработка исключений (а в будущем, возможно, и многопоточность)
планировалось реализовать как внешние библиотечные средства -- но против
такого подхода также есть серьезные возражения.
Впрочем, что бы не планировали разработчики -- окончательный выбор, как
мы надеемся, будет принадлежать самим пользователям языка.
Заключение
В заключение приведем небольшой, но вполне реалистичный пример
завершенного Ксерион-модуля, реализующего простейшие операции над
комплексными числами.
!!
!! Исходный файл: "complex.xrn"
!! Реализация класса `complex`:
!! комплексные числа (иммутабельные)
!!
!! внешние функции (в реальной программе импортируемые):
double (double x, y) #atan2; !! двухаргументный арктангенс
double (double x, y) #hypot; !! гипотенуза
double (double x) #sqrt; !! квадратный корень
class complex {
!! компоненты класса
double Re, Im; !! (real, imag)
!! [Унарные операции над %complex]
%complex (%complex op1) %opUnary;
%opUnary #conj; !! Сопряжение
%opUnary #neg; !! Отрицание
%opUnary #sqrt; !! Квадратный корень
!! [Бинарные операции над %complex]
%complex (%complex op1, op2) %opBinary;
%opBinary #add; !! Сложение
%opBinary #sub; !! Вычитание
%opBinary #mul; !! Умножение
%opBinary #div; !! Деление
!! Проверка на нуль
bool () is_zero { return Re -- 0f && Im -- 0f };
!! [Сравнения для %complex]
bool (%complex op1, op2) %opCompare;
!! (на равенство):
%opCompare eq { return op1.Re -- op2.Re && op1.Im -- op2.Im };
!! (на неравенство):
%opCompare ne { return op1.Re <> op2.Re || op1.Im <> op2.Im
};
!! Модуль
double (%complex op) mod { return hypot (op.Re, op.Im) };
!! Аргумент
double (%complex op) arg { return atan2 (op.Re, op.Im) };
};
!! Реализация предекларированных функций
!! Сопряженное для op1
#complex.conj { return #(op1.Re, - op1.Im) };
!! Отрицание op1
#complex.neg { return #(- op1.Re, - op1.Im) };
!! Сложение op1 и op2
#complex.add { return #(op1.Re + op2.Re, op1.Im + op2.Im) };
!! Вычитание op1 и op2
#complex.sub { return #(op1.Re - op2.Re, op1.Im - op2.Im) };
!! Произведение op1 и op2
#complex.mul {
return #(op1.Re * op2.Re - op1.Im * op2.Im,
op1.Im * op2.Re + op1.Re * op2.Im)
};
!! Частное op1 и op2
#complex.div {
!! (делитель должен быть ненулевой)
assert ~op2.is_zero ();
double denom = op2.Re * op2.Re + op2.Im * op2.Im;
return # ((op1.Re * op2.Re + op1.Im * op2.Im) / denom,
- (op1.Re * op2.Im + op2.Re * op1.Im) / denom)
};
let g_sqrt = sqrt; !! (глобальная функция `sqrt`)
!! Квадратный корень из op1 (одно из значений)
#complex.sqrt {
double norm = complex.mod (op1);
return #(g_sqrt ((norm + op1.Re) / 2f), g_sqrt ((norm - op1.Re) / 2f))
};
!!
!! Операции для работы с complex
!!
!! унарный '-' как отрицание
opdef -complex = complex.neg ((<1>));
!! унарный '~' как сопряжение
opdef ~complex = complex.conj ((<1>));
!! бинарный '+' как сложение
opdef complex + complex = complex.add ((<1>), (<2>));
!! бинарный '-' как вычитание
opdef complex - complex = complex.sub ((<1>), (<2>));
!! бинарный '*' как умножение
opdef complex * complex = complex.mul ((<1>), (<2>));
!! бинарный '/' как деление
opdef complex / complex = complex.div ((<1>), (<2>));