代码之家  ›  专栏  ›  技术社区  ›  oxbow_lakes

我可以用虚拟类做什么?

  •  20
  • oxbow_lakes  · 技术社区  · 15 年前

    我听说过很多关于添加 虚拟课堂 去斯卡拉(它已经 virtual types ,根据 Martin Odersky )

    对于虚拟类型是什么,外行的观点是什么(可能举个例子) 有什么可能 scala有虚拟类吗?

    ( [我没有C或C++的经验,所以宁愿选择任何不引用这些语言的答案] )

    1 回复  |  直到 9 年前
        1
  •  18
  •   Lionel Parreaux    9 年前

    虚拟类型很简单:

    • 类和特性可以有类型成员。例如。

      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
      }
      

    这里是 an example of virtual classes in a Java-descendent language ( cclass 是虚拟类):

    虚拟类的特性

    让我们看看 以另一个例子来研究 虚拟类的可能性。我们 将使用虚拟类扩展 与全新的 功能性。假设我们有一个核心 表示表达式的数据模型:

    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类 实现 具有两个操作数的所有表达式。 请注意,当前版本的 凯撒不支持构造函数 带参数和抽象方法 在C类中。下面的代码演示 如何生成示例表达式 使用这种协作:

    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的子类。这意味着 常量被隐式假定为 exprformat中expr的子类 好。

    • 虚拟类可以使用在其 旧版本。例如 exprformat.binaryexpr可以使用字段 _ exprmodel.binaryexpr中定义的“左”和“右”。

    • 重写的虚拟类中定义的功能可以 不使用类型转换访问。为了 示例,字段“左”和“右” BinaryExpr最初被声明 expr类型为exprmodel,其中 没有方法format(),但位于 exprformat的上下文 将expr的版本假定为类型 左边和右边。因此,格式() 在没有任何类型转换的情况下调用。

    • 重写的虚拟类中引入的方法可以 在新版本中再次重写 子类的例如,重写 expr引入了方法format(),其中 不能在BinaryExpr中重写。同时 添加和mult不重写此 方法更进一步,它们继承 binaryexpr的format()。

    除了演示的特性外, 重写的虚拟类可以 也

    • 引入新的数据字段,
    • 实现新的接口,
    • 引入新的继承关系。
    推荐文章