Что я могу сделать с виртуальными классами? - PullRequest
20 голосов
/ 14 июня 2010

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

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

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

1 Ответ

18 голосов
/ 14 июня 2010

Виртуальные типы просты:

  • Классы и черты могут иметь членов типа. Э.Г.

    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 of BinaryExpr были первоначально объявлены с типом Expr ExprModel, который не имеет метода format (), но в контекст ExprFormat новый версия Expr предполагается в качестве типа из левых и правых. Так что format () может вызываться без приведения типов.

  • Методы, представленные в переопределенных виртуальных классах, могут быть снова переопределено в новых версиях подклассов. Например переопределено Expr представляет метод format (), который может быть переопределено в BinaryExpr. В то время как Add и Mult не отменяют это Метод далее, они наследуют формат () BinaryExpr.

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

  • ввести новые поля данных,
  • реализовать новые интерфейсы,
  • ввести новые отношения наследования.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...