我已经看到(并听到)关于向Scala 添加虚拟类的相当多的噪音(根据Martin Odersky的说法,它已经有虚拟类型).
什么是虚拟类型是什么,外行人的观点(可能是一个例子)是什么?Scala有什么可能的虚拟类?
([我没有使用过C或C++的经验,所以我希望任何答案都不要参考这些语言].)
Ale*_*nov 18
虚拟类型很简单:
类和特征可以具有类型成员.例如
trait Foo {
type T
}
Run Code Online (Sandbox Code Playgroud)它们可以被细化(但一旦定义就不会被覆盖):
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
}
Run Code Online (Sandbox Code Playgroud)以下是Java-descendent语言中虚拟类的示例(cclass是一个虚拟类):
虚拟课程的特点
让我们看另一个例子来研究虚拟类的可能性.我们将使用虚拟课程以全新的功能扩展协作.假设我们有一个核心数据模型来表示表达式:
Run Code Online (Sandbox Code Playgroud)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类使用两个操作数实现所有表达式的通用功能.请注意,当前版本的Caesar不支持在cclass中使用参数和抽象方法的构造函数.下面的代码演示了如何使用这种协作构建示例表达式:
Run Code Online (Sandbox Code Playgroud)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类使用两个操作数实现所有表达式的通用功能.
有许多与表达式相关的不同功能:它们的评估,将表达式格式化为简单文本的中缀或后缀顺序,各种一致性检查,查找和转换.我们希望将所有这些特定功能彼此分离并与核心数据模型分开.这可以通过虚拟类来实现.例如,下面的协作使用简单的表达式格式化功能扩展了核心模型:
Run Code Online (Sandbox Code Playgroud)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将Constant定义为Expr的子类.这意味着Constant也被隐式假设为ExprFormat中Expr的子类.
虚拟类可以使用旧版本中定义的字段和方法.例如,ExprFormat.BinaryExpr可以使用ExprModel.BinaryExpr中定义的_left和_right字段.
可以在不使用类型转换的情况下访问已重写的虚拟类中定义的功能.例如,字段_Left和BinaryExpr的_right最初用)ExprModel的类型Expr的,其不具有方法格式(声明,但在ExprFormat的上下文expr的新版本被假定为_Left和_right的类型.因此可以在没有任何类型转换的情况下调用format().
在覆盖的虚拟课堂中引入的方法可以再次重写在子类中的新版本.例如重写Expr的介绍方法格式(),其可以在BinaryExpr被覆盖.虽然添加和MULT不会进一步重写此方法,它们继承BinaryExpr的格式().
除了演示的属性外,重写的虚拟类也可以
- 介绍新的数据字段,
- 实现新的接口,
- 引入新的继承关系.
| 归档时间: |
|
| 查看次数: |
3020 次 |
| 最近记录: |