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 类型检查和转换
Scala | Java |
---|---|
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();
相关文章推荐
- scala面向对象编程 - 类、抽象类、伴生对象、继承、类的构造方法
- 第10节:scala面向对象编程中的继承
- Javascript面向对象编程(三):非构造函数的继承
- 在JavaScript面向对象编程中使用继承(4)
- scala之继承
- C++学习6-面向对象编程基础(运算符重载、类的派生与继承、命名空间)
- Js中面向对象编程之继承的几种方式及理解
- C++面向对象编程,继承,数据抽象,动态绑定
- Scala入门学习之【类,对象,继承】
- Scala面向对象编程之对象
- Javascript面向对象编程(三):非构造函数的继承
- Javascript面向对象编程(二):构造函数的继承
- Scala class的构造方法与继承
- 快学Scala习题解答—第八章 继承
- Javascript面向对象编程(三):非构造函数的继承
- Javascript面向对象编程(三):非构造函数的继承
- Javascript面向对象编程:构造函数的继承
- Python面向对象编程(类和实例 访问限制 继承和多态 获取对象信息 实例属性和类属性)
- scala学习手记13 - 类继承
- Javascript面向对象编程(二):构造函数的继承