Ответ 1
Виртуальные типы просты:
-
Классы и черты могут иметь члены типа. Например.
trait Foo { type T }
-
Они могут быть уточнены (но не переопределены после их определения):
class Foo1 extends Foo { type T <: AnyVal } class Foo2 extends Foo1 { override type T = Boolean } class Foo3 extends Foo2 { // override type T = Int // rejected by the compiler – would be unsound }
Вот пример виртуальных классов на языке Java-потомков (cclass
- это виртуальный класс):
Особенности виртуальных классов
Посмотрим к другому примеру, чтобы изучить возможности виртуальных классов. Мы будет использовать виртуальные классы для расширения сотрудничество с совершенно новым Funtionality. Допустим, у нас есть ядро модель данных для представления выражений:
public cclass ExprModel { abstract public cclass Expr {} public cclass Constant extends Expr { protected int _val; public Constant(int val) { _val = val; } } abstract public cclass BinaryExpr { protected Expr _left; protected Expr _right; public BinaryExpr(Expr left, Expr right) { _left = left; _right = right; } } public cclass Add extends BinaryExpr {} public cclass Mult extends BinaryExpr {} }
Сотрудничество определяет Expr как базовый класс для всех выражений, конкретные классы для представления константы, добавление и умножение. Класс BinaryExpr реализует общую функциональность все выражения с двумя операндами. Обратите внимание, что текущая версия Цезарь не поддерживает конструкторы с параметрами и абстрактными методами в классе. Приведенный ниже код демонстрирует как можно создавать образцы выражений используя такое сотрудничество:
public model.Expr buildSampleExpr(final ExprModel model) { model.Expr const1 = model.new Constant(-3); model.Expr const2 = model.new Constant(2); model.Expr op1 = model.new Mult(const1, const2); model.Expr const3 = model.new Constant(5); model.Expr op2 = model.new Add(op1, const3); return op2; }
Сотрудничество определяет Expr как базовый класс для всех выражений, конкретные классы для представления константы, добавление и умножение. Класс BinaryExpr реализует общую функциональность все выражения с двумя операндами.
Есть много разных функциональность, связанная с выражения: их оценка, форматирование выражений для простого текста в инфиксном или постфиксном порядке, различные проверки целостности, поиск и преобразования. Мы хотим сохранить все эта специфическая функциональность отделена друг от друга и из основных данных модель. Это может быть достигнуто с помощью помощь виртуальных классов. Например, сотрудничество ниже расширяет ядро с простым выражением функциональность форматирования:
public cclass ExprFormat extends ExprModel { abstract public cclass Expr { abstract public void String format(); } public cclass Constant { public void String format() { return _val < 0 ? "(" + _val + ")" : "" + _val; } } abstract public cclass BinaryExpr { public void String format() { return "(" + _left.format() + getOperSymbol() + _right.format() + ")"; } abstract public void String getOperSymbol(); } public cclass Add { public void String getOperSymbol() { return "+"; } } public cclass Mult { public void String getOperSymbol() { return "*"; } } }
Этот короткий пример демонстрирует различные возможности виртуальных классов:
Нет необходимости повторять отношения наследования между виртуальные классы, если они уже определенных в суперконце- рации. Для Пример ExprModel определяет константу как подкласс Expr. Это означает, что Константа подразумевается неявно подкласс Expr в ExprFormat as хорошо.
Виртуальные классы могут использовать поля и методы, определенные в их более старые версии. Например ExprFormat.BinaryExpr может использовать поля _left и _right, определенные в ExprModel.BinaryExpr.
Функциональность, определенная в переопределенных виртуальных классах, может быть доступ к ним без типов. Для Например, поля _left и _right Первоначально объявлено BinaryExpr с типом Expr ExprModel, который не имеет формата метода(), но в контекст ExprFormat нового версия Expr считается типом ofleft и _right. Таким образом, формат() может вызывать без каких-либо типов.
Методы, введенные в переопределенные виртуальные классы, могут быть снова переопределяется в новых версиях подклассов. Например, переопределение Expr вводит формат метода(), который может быть переопределено в BinaryExpr. В то время как Добавить и Mult не переопределяют это Кроме того, они наследуют format() BinaryExpr.
Помимо продемонстрированных свойств, переопределенные виртуальные классы могут также
- ввести новые поля данных,
- реализовать новые интерфейсы,
- ввести новые отношения наследования.