您的位置:首页 > 编程语言

Scala 面向对象编程之继承

2018-03-03 20:31 281 查看

Scala 面向对象编程之继承

1. Scala 中继承(extends) 的概念

Scala 中,让子类继承父类,与 Java 一样,也是使用 extends 关键字;

继承就代表子类可继承父类的 field 和 method ,然后子类还可以在自己的内部实现父类没有的,子类特有的 field 和 method,使用继承可以有效复用代码;

子类可以覆盖父类的 field 和 method,但是如果父类用 final 修饰,或者 field 和method 用 final 修饰,则该类是无法被继承的,或者 field 和 method 是无法被覆盖的。

private 修饰的 field 和 method 不可以被子类继承,只能在类的内部使用;

field 必须要被定义成 val 的形式才能被继承,并且还要使用 override 关键字。 因为 var 修饰的 field 是可变的,在子类中可直接引用被赋值,不需要被继承;即 val修饰的才允许被继承,var 修饰的只允许被引用。继承就是改变、覆盖的意思。

Java 中的访问控制权限,同样适用于 Scala

权限类内部本包子类外部包
public
protected
default
private

2. Scala 中 中 override 和 和 super 关键字

Scala 中,如果子类要覆盖父类中的一个非抽象方法,必须要使用 override 关键字;

子类可以覆盖父类的 val 修饰的 field,只要在子类中使用 override 关键字即可。

override 关键字可以帮助开发者尽早的发现代码中的错误,比如, override 修饰的父类方法的方法名拼写错误。

此外,在子类覆盖父类方法后,如果在子类中要调用父类中被覆盖的方法,则必须要使用 super 关键字,显示的指出要调用的父类方法。

3. Scala 中 中 isInstanceOf 和 和 asInstanceOf

如果实例化了子类的对象,但是将其赋予了父类类型的变量,在后续的过程中,又需要将父类类型的变量转换为子类类型的变量,应该如何做?

首先,需要使用 isInstanceOf 判断对象是否为指定类的对象,如果是的话,则可以使用 asInstanceOf 将对象转换为指定类型;

注意: p.isInstanceOf[XX] 判断 p 是否为 XX 对象的实例;p.asInstanceOf[XX] 把 p转换成 XX 对象的实例

注意:如果没有用 isInstanceOf 先判断对象是否为指定类的实例,就直接用asInstanceOf 转换,则可能会抛出异常;

注意:如果对象是 null,则 isInstanceOf 一定返回 false, asInstanceOf 一定返回null;

Scala 与 Java 类型检查和转换

ScalaJava
obj.isInstanceOf[C]obj instanceof C
obj.asInstanceOf[C](C)obj
classOf[C]C.class

4. Scala 中 中 getClass 和 和 classOf

isInstanceOf 只能判断出对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象;

如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf了;

p.getClass 可以精确地获取对象的类,classOf[XX] 可以精确的获取类,然后使用 ==操作符即可判断

5. Scala 中使用模式匹配进行类型判断

在实际的开发中,比如 spark 源码中,大量的地方使用了模式匹配的语法进行类型的判断,这种方式更加地简洁明了,而且代码的可维护性和可扩展性也非常高;

使用模式匹配,功能性上来说,与 isInstanceOf 的作用一样,主要判断是否为该类或其子类的对象即可,不是精准判断。

等同于 Java 中的 switch case 语法;

6. Scala 中 中 protected

跟 Java 一样,Scala 中同样可使用 protected 关键字来修饰 field 和 method。在子类中,可直接访问父类的 field 和 method,而不需要使用 super 关键字;

还可以使用 protected[this] 关键字, 访问权限的保护范围:只允许在当前子类中访问父类的 field 和 method,不允许通过其他子类对象访问父类的 field 和 method。

7. Scala 中调用父类的 constructor

Scala 中,每个类都可以有一个主 constructor 和任意多个辅助 constructor,而且每个辅助 constructor 的第一行都必须调用其他辅助 constructor 或者主 constructor代码;因此子类的辅助 constructor 是一定不可能直接调用父类的 constructor 的;

只能在子类的主 constructor 中调用父类的 constructor。

如果父类的构造函数已经定义过的 field,比如 name 和 age,子类再使用时,就不要用 val 或 var 来修饰了,否则会被认为,子类要覆盖父类的 field,且要求一定要使用 override 关键字。

8. Scala 中匿名内部类

在 Scala 中,匿名内部类是非常常见的,而且功能强大。Spark 的源码中大量的使用了匿名内部类;

匿名内部类,就是定义一个没有名称的子类,并直接创建其对象,然后将对象的引用赋予一个变量,即匿名内部类的实例化对象。然后将该对象传递给其他函数使用。

9. Scala 中抽象类

如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现不同的方法。此时,可以将父类中的这些方法编写成只含有方法签名,不含方法体的形式,这种形式就叫做抽象方法;

一个类中,如果含有一个抽象方法或抽象 field,就必须使用 abstract 将类声明为抽象类,该类是不可以被实例化的;

在子类中覆盖抽象类的抽象方法时,可以不加 override 关键字;

10. Scala 中抽象 field

如果在父类中,定义了 field,但是没有给出初始值,则此 field 为抽象 field;

喜欢就点赞评论+关注吧



感谢阅读,希望能帮助到大家,谢谢大家的支持!

$(".MathJax").remove();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息