Scala学习:调用超类构造器和override修饰符的使用

开发 后端
本文节选自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻译的《Programming in Scala》的第十章。Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言。

调用超类构造器

现在你有了两个类组成的完整系统:抽象类Element,和扩展它的具体类ArrayElement。或许你还在设想其它表达元素的方式。比方说,客户或许想要创造由给定单行字串构成的布局元素。面向对象编程让使用新数据变体扩展系统变得容易。只要加入子类即可。例如,代码10.6展示了扩展ArrayElement的LineElement类:

  1. class LineElement(s: String) extends ArrayElement(Array(s)) {  
  2.  override def width = s.length  
  3.  override def height = 1 
  4. }  

代码 10.6 调用超类构造器

51CTO编辑推荐:Scala编程语言专题

由于LineElement扩展了ArrayElement,并且ArrayElement的构造器带一个参数(Array[String]),LineElement需要传递一个参数到它的超类的主构造器。要调用超类构造器,只要把你要传递的参数或参数列表放在超类名之后的括号里即可。例如,类LineElement传递了Array(s)到ArrayElement的主构造器,把它放在超类ArrayElement的名称后面的括号里:

  1. ... extends ArrayElement(Array(s)) ...  
有了新的子类,布局元素的继承级别现在看起来就像展示在图释10.2中的那样了。

 LineElement的类关系图

图释 10.2 LineElement的类关系图

使用override修饰符

请注意LineElement里width和height的定义带着override修饰符。你在6.3节中的 toString方法中看到过。Scala里所有重载了父类具体成员的成员都需要这样的修饰符。如果成员实现的是同名的抽象成员则这个修饰符是可选的。而如果成员并未重载或实现什么其它基类里的成员则禁用这个修饰符。由于类LineElement的height和width重载了类Element的具体成员定义,override是需要的。

这条规则给编译器提供了有用的信息来帮助避免某些难以捕捉的错误并使得系统的改进更加安全。例如,如果你碰巧拼错了方法名或偶尔传递给它不同的参数列表,编译器会回应错误信息:

  1. $ scalac LineElement.scala  
  2. .../LineElement.scala:50:  
  3. error: method hight overrides nothing  
  4. override def hight = 1 
  5. ˆ  
系统改进的时候,override公约显得更重要。假设你定义了一个2D画图方法库。你把它公开,并广泛使用。库的下一个版本里你想在你的基类Shape里增加一个使用以下签名的新方法:

  1. def hidden(): Boolean 
你的新方法将被用在许多画图方法中去决定是否需要把形状画出来。这或许会产生显著的提速,但你不可以冒着破坏客户代码的风险做这件事。毕竟客户说不定已经使用不同的hidden实现定义了Shape的子类。或许客户的方法实际上是让对象消失而不是检测是否对象是隐藏的。因为这两个版本的hidden互相重载,你的画图方法将停止对象的消失,这可真不是你想要的!这些“意外的重载”就是被称为“脆基类”问题的最通常的表现。这个问题是指如果你添加了新的成员到类层级的基类中(通常我们称为超类),你会有破坏客户代码的风险。

Scala不能完全解决脆基类问题,不过它与Java相比有所改善。Java1.5中,@Override标注被引入并与Scala的override修饰符起相同的工作,不过不像Scala的override,它不是必需的。如果画图库和它的客户是用Scala写的,那么客户的hidden原始实现就不会有override修饰符,因为这时候还没有另外一个使用那个名字的方法。一旦你添加了hidden方法到你Shape类的第二个版本,客户的重编译将给出像下列这样的错误:

  1. .../Shapes.scala:6: error: error overriding method  
  2. hidden in class Shape of type ()Boolean;  
  3. method hidden needs 'override' modifier  
  4. def hidden(): Boolean =  
  5. ˆ  

也就是说,代之以错误的执行,你的客户将得到一个编译期错误,这常常是更可取的。

【相关阅读】

  1. Scala:重载方法和字段及定义参数化字段
  2. Scala程序中的扩展类
  3. 在Scala中定义无参数方法
  4. 学习Scala的二维布局库和抽象类
  5. Scala学习:叫名参数by-name parameter

责任编辑:book05 来源: Artima
相关推荐

2009-08-24 16:49:39

C#修饰符

2009-06-19 10:51:39

Scalapackage访问修饰符

2011-06-02 14:51:07

JAVA修饰符

2023-12-29 09:01:27

SwiftUI视图修饰符

2009-08-27 11:16:40

C# sealed修饰

2009-08-27 11:12:03

C# abstract

2009-08-21 13:58:06

C# virtual修

2011-05-13 14:56:14

autoregisterstatic

2009-08-27 13:06:13

C# new修饰符

2009-09-02 17:14:28

C#修饰符

2009-08-27 11:04:08

C# extern修饰

2009-09-02 17:04:35

C# Extern修饰

2009-12-11 10:42:00

Scala讲座类定义构造函数

2009-09-04 11:06:40

C#访问修饰符

2015-08-18 09:25:11

Java修饰符关键词

2009-07-21 12:35:00

Scala从构造器

2011-06-28 09:29:11

C#修饰符

2009-06-12 13:37:47

访问权限修饰符Java教程

2009-06-12 14:46:05

static修饰符Java教程

2021-08-02 12:33:26

Swift修饰符视图
点赞
收藏

51CTO技术栈公众号