`
wbj0110
  • 浏览: 1611474 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

scala --继承

阅读更多

继承类

使用extends关键字来继承一个类。如果将类声明为final的,则这个类不能被继承。如果将类的方法和字段声明为final,则它们不能被重写。

重写方法

在Scala中重写一个非抽象方法必须使用override修饰符。调用超类的方法就如Java一样,使用super关键字。

类型检查和转换

使用isInstanceOf方法来检测某个对象是否为某个特定的类;如果检测通过,则可以使用asInstanceOf方法来将对象转换为子类。

如果p是null,p.isInstanceOf[Employee]将会返回false;如果p不是Employee,则会抛出一个异常。

如果说需要检查p是一个Employee而且不是其子类,则如下使用:

还有个更好的选择,使用模式匹配:

 

protected字段和方法

用protected修饰符声明的字段和方法,可以被子类访问,但不能从其他位置访问。要注意,protected成员在当前类所属的包来说,也是不可见的,这是与Java不同的。

Scala提供了与private[this]类似的protected[this]。

超类的构造

在学习构造器时可以知道,辅助构造器最终都会调用主构造器。在Scala中,只有主构造器才能主动调用超类的构造器。

主构造器是与类的定义混合在一起的,调用超类构造器也是与类的定义交织在一起的。

 

重写字段

因为Scala的字段是由私有字段和setter/getter共同组成的,所以在重写的时候,对于不同类型的声明会有不同的限制。

声明的类型有val、var和def。限制:

现学现卖用HTML画的表格   用val 用def 用var
重写val
  • 子类有一个私有字段
  • getter方法重写超类的getter方法
错误 错误
重写def
  • 子类有一个私有字段
  • getter方法重写超类的getter方法
和Java一样 重写getter/setter,只重写getter报错
重写var 错误 错误 仅当超类的var是抽象的才可以

从这里看来,使用var是个很不好的选择。不过我暂时还不知道有什么样更好的方案。

 

匿名子类

 

从技术上讲,这会创建出一个结构类型的对象。结构类型要到后面才能细说。类型标记为 Person{def greeting: String}。可以将这个类型作为参数类型的定义:

 

抽象类

用abstract关键字来标记不能被实例化的类。如果某个类存在抽象方法,该类就必须是abstract的。

但抽象方法不需要使用abstract关键字,只要将方法体留为空即可。

重写超类的抽象方法时,不需要使用override关键字。

 

抽象字段

没有初始值的字段即是抽象字段。根据是val声明还是var声明,会生成相应的抽象的setter/getter。但是不生成字段。

查看编译后的字节码,可以得知,JVM类只生成了setter/getter,但没有生成字段。

 

构造顺序和提前定义(L3)

这个主题好高的技能等级…不过看下来也挺好理解。这个等级说明的是要求等级,而不是难度等级。

现有如下的类:

在构造时,发生的过程如下:

  1. Ant构造器在构造自己之前,调用超类构造器;
  2. Creature的构造器将range字段设为10;
  3. Creature的构造器初始化env数组,调用range字段的getter;
  4. range的getter被Ant类重写了,返回的Ant类中的range,但是Ant类还未初始化,所以返回了0;
  5. env被设置成长度为0的数组
  6. Ant构造器继续执行,将range字段设为2。

在Java中也会出现碰见相似的问题,被调用的方法被子类所重写,有可能结果不是预期的。在构造器中,不应该依赖val的值。(只能重写超类抽象的var声明字段,所以没有这个问题;如果是def,也一样会出现这种问题。)

这个问题的根本原因来自于Java语言的设计决定——允许在超类的构造方法中调用子类的方法。而在C++中,构造前后会更改指向虚函数的指针,所以不会出现这类问题。

这个问题有几种解决方法:

  • 将val声明为final,安全但不灵活;
  • 在超类中将val声明为lazy,安全但不高效;
  • 使用提前定义语法。

提前定义语法真的如书上所说——难看到家了,估计没人会喜欢。将需要提前定义的成员放在extends关键字后的一个语法块中,还需要使用with关键字:

提前定义的等号右侧只能引用之前已经有的提前定义,不能出现类中其他的成员(因为都还没初始化呢)。

Tip:

使用-Xcheckinit编译器标志来调试构造顺序问题。这个标志会在有未初始化的字段被访问时抛出异常。

Scala继承层级

这个还是搭配图来看比较好,这里贴的是《Programming in Scala》一书的图。

与Java中基本类型对应的类,以及Unit类,都继承自AnyVal。所有其他的类都继承自AnyRef,AnyRef相当于Java中的Object类。

AnyVal和AnyRef都继承自Any类,Any类是整个层级的根节点。Any类定义了isInstanceOf、asInstanceOf方法,以及用于相等性判断和哈希码的方法。

AnyVal没有添加任何方法,只是所有值类型的一个标记。AnyRef追加了来自Object类的监视方法wait和notify/notifyAll,同时提供了一个带函数参数的方法synchronized,等同于Java中的synchronized块。

所有Scala类都实现ScalaObject这个特质,这个特质没有定义任何方法。(ScalaObject在2.10.0版本后被移除了。)

在层级的另一端,Null是所有AnyRef类型的子类型;Nothing是所有类型的子类型。

Null类的唯一实例是null值。可以将null赋值给引用类型,但不能赋值给值类型。Nothing类型没有实例,但对泛型结构时常有用。比如,空列表Nil的类型是List[Nothing],是List[T]的子类型。

Noting类型与其他语言中出现的void是没有关系的。Scala中void由Unit类型表示,Unit类型只有一个值,( )。虽然Unit不是其他类型的超类,但是编译器允许任何值被体换成( )。

 

对象相等性(L1)

AnyRef的eq方法会检查两个引用是否指向同一个对象。而AnyRef的equals方法默认是调用eq方法的,也就是说,equals默认实现是检查两个引用是否是同一个对象。如果需要其他的相等性判断,就需要重写equals方法。

当定义equals时,也需要同时重写hashCode方法。计算哈希码时,应该只使用用来做相等性判断的字段来进行。

在应用程序当中,通常不直接调用eq或equals方法,使用==操作符就好了。对于引用类型来说,==操作符会在做完必要的null检查之后调用equals方法。


本章习题参考。只能作为小小的参考。

4.

 

 

分享到:
评论

相关推荐

    Scala-2.11.1.zip

    2. **面向对象编程**:Scala支持传统的面向对象编程,包括类、接口、继承和多态。不过,它还引入了特质(trait),这是一种更轻量级的继承方式,可以用来实现多重继承和混合行为。 3. **函数式编程**:Scala是函数...

    scala-intellij-bin-2020.2.3.zip

    - **特质(Traits)**:提供了一种实现多重继承的机制。 - **函数式编程**:Scala支持lambda表达式和不可变数据结构,鼓励函数式的编程风格。 2. **IntelliJ IDEA Scala插件**: - **语法高亮**:插件提供了...

    scala-2.12.11.zip

    4. **面向对象编程**:Scala也是面向对象的,支持类、对象、继承、封装和多态。特别的是,Scala的每一切都是一个对象,包括函数,这使得函数可以作为第一类公民来处理。 5. ** Actors模型**:Scala内置了Akka库,...

    scala-2.12.10.zip

    Scala的语法优雅且富有表达力,它允许开发者使用函数式编程的特性,如高阶函数、柯里化、模式匹配和不可变数据结构,同时保留了面向对象的类、接口和继承。这使得Scala成为处理大数据、并发和分布式计算的理想选择,...

    scala-intellij-bin-2021.3.6.zip

    5. **对象和类**:Scala将面向对象和函数式编程结合在一起,支持单例对象和特质(trait),可以方便地实现混合继承和多重继承。 IntelliJ IDEA作为IDE,提供了以下对Scala开发者的支持: 1. **智能代码补全**:...

    scala-intellij-bin-2019.2.20.zip

    - 面向对象编程:支持类、接口、继承、多态等面向对象概念。 - REPL(Read-Eval-Print Loop):交互式编程环境,便于测试和调试代码。 - 强大的IDE集成:代码提示、重构工具、快速导航、代码分析等,提高开发效率。 ...

    scala-intellij-bin-2016.3.1.zip

    IDE的Scala插件会帮助开发者管理和使用特质,避免可能出现的复杂继承问题。 除此之外,IntelliJ IDEA的Scala插件还支持Akka、Play Framework等基于Scala的流行框架。Akka是一个用于构建高度并发、分布式和反应式的...

    scala-intellij-bin-2019.2.28.zip

    4. **面向对象编程**:Scala是面向对象的语言,支持类、对象和继承。同时,它引入了特质(trait)作为实现多继承和行为组合的方式。 5. ** Actors模型**:Scala集成了Akka库,提供了Actor模型来处理并发和分布式...

    scala-intellij-bin-2017.3.11.zip

    - **面向对象编程**:提供了类、特质(trait)和继承,同时支持多态和抽象类型。 - ** Actors模型**:Scala内置对Akka Actors的支持,用于构建分布式、反应式和容错的应用程序。 2. **IntelliJ IDEA Scala插件**...

    scala-2.11.8.tgz.zip

    4. **复合**:Scala鼓励使用组合而非继承来构造软件组件,这有助于代码的重用和维护。 5. **表达式导向**:Scala的语法设计使得大部分代码都可以作为表达式执行,每个表达式都有一个结果,这与C风格的语句有所不同...

    scala-2.12.10.tgz

    8. 面向对象编程:Scala是面向对象的,支持类、接口、继承和多态。它还引入了特质(Traits),一种可组合的行为单元,增强了代码的复用和模块化。 9. Akka框架:Scala广泛用于构建分布式系统,尤其是与Akka框架结合...

    scala-intellij-bin-2.2.0.zip

    - **面向对象**:Scala支持类、对象和继承,同时也提供了模块化设计的手段,如包和包对象。 - **函数式编程**:Scala中函数是一等公民,可以作为值传递,也可以作为返回结果。它支持高阶函数、闭包和惰性求值。 - **...

    scala-2.11.0-M5

    6. **特质**:类似于Java的接口,但可以包含实现,可以用来实现多重继承。 7. **类型系统增强**:如类型别名、类型推导、类型成员和类型参数化。 Scala的2.11版本引入了一些重要的改进,包括: 1. **更好的互操作性...

    scala-2.11.7-windows

    2. **面向对象编程**:Scala支持类、接口和继承,同时引入了特质(trait),这是一种轻量级的抽象类型,可以用来实现多重继承和混合行为。 3. **函数式编程**:Scala鼓励函数式编程风格,提供了高阶函数、不可变...

    scala-intellij-bin-2020.1.27.zip

    Scala的面向对象特性体现在类、继承、封装和多态等概念上,与Java相似但更加强大。例如,Scala中的所有数据类型都是对象,这使得函数可以像对象一样被处理,反之亦然,这种特性被称为“函数式对象”或“一切皆对象”...

    scala-2.10.6.tgz

    - **面向对象**:Scala支持类、对象和继承,同时也引入了特质(trait),提供了一种更灵活的实现多继承的方式。 - **函数式编程**:Scala内置了高阶函数和不可变数据结构,使得函数式编程风格成为可能,这对于并行...

    scala-2.10.5.tgz

    6. **对象编程**:Scala的类和对象设计支持单例对象、抽象类、特质(trait)和多重继承,这提供了高度灵活的面向对象设计。 7. **嵌套函数和局部类型推断**:Scala允许在类或对象内部定义函数,这样可以创建更模块...

    scala-docs-2.11.8.rar

    4. **面向对象编程**:Scala是面向对象的语言,支持类、对象、继承、封装和多态等概念。 5. **Actor模型**:Scala集成了Akka框架,提供了一种基于Actor的并发模型,用于构建分布式、容错的应用程序。 **二、Scala ...

    scala-2.12.3

    6. **复合**:Scala鼓励使用复合而不是继承来构建软件,以减少代码的耦合度和提高可维护性。 7. **泛型**:与Java类似,Scala也支持泛型,允许编写通用的代码,以适应多种数据类型。 8. **集合库**:Scala的集合库...

    scala-docs-2.11.1.zip

    类和对象是构建Scala程序的基础,而特质(trait)则提供了一种灵活的继承和复用机制。函数在Scala中是第一等公民,可以作为值传递,存储在变量中,甚至作为其他函数的参数或返回值。 `2.11.1`是Scala的一个重要版本...

Global site tag (gtag.js) - Google Analytics