Что я могу сделать с виртуальными классами?

Я видел (и слышал) довольно много шума о добавлении виртуальных классов в Scala (у него уже есть виртуальные типы, согласно Мартин Одерский).

Что такое перспектива непрофессионала (возможно, пример) в том, что такое виртуальный тип, и , что может быть возможно, были Scala для виртуальных классов?

([У меня нет опыта работы с C или С++, поэтому предпочел бы, чтобы любой ответ не ссылался на эти языки].)

Ответ 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.

Помимо продемонстрированных свойств, переопределенные виртуальные классы могут также

  • ввести новые поля данных,
  • реализовать новые интерфейсы,
  • ввести новые отношения наследования.