ания (что вряд ли приемлимо), множественное наследование только от специальных абстрактных классов-интерфейсов (такой подход принят в 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>));