继承
一.会继承父类的私有成员吗
会的,只是没有办法访问而已(可以debug一下)
二.重写方法
scala明确规定,重写一个非抽象方法需要用override修饰符,调用超类的方法使用super关键字
class Person { def printName() { println("Person") } } class Emp extends Person { override def printName() { println("emp") } //调用自己的printName,直接写方法名,调用父类的,使用super }
三.Scala中类型检查和转换
| classOf[类名] | 返回全类名 | 
| 变量.getClass.getName | 通过反射获取变量的全类名 | 
| isInstanceOf | 对象是否是特定类的一个实例 | 
| asInstanceOf | obj.asInstanceOf[T](运行的前提:obj对应的地址可以使用这个类型)会返回一个类型为T,地址和obj一样的对象 [看下图] | 

个人理解:isInstanceOf是对java堆中的对象的类型进行判断,asInstanceOf是针对栈中变量的类型转换,调用方法时看的是变量的类型,变量的类型对应的类有哪些方法,就可以调用哪些方法。
四.超类
子类调用父类的那个构造器由什么来决定?
调用父类构造只能由extends后面父类的参数列表来实现,不能通过其他的语句,感觉这里的参数说实参比较好
class cat(ename:String,age:Int) extends Animals(ename) 反编译之后,ename,age也是在构造器生成两个变量 class cat(ename:String,age:Int) extends Animals("hello")
五.覆写/重写字段
①在Java中
只有方法的重写,没有属性/字段的重写,准确的讲,是隐藏字段代替了重写。在java官方提供的tutorial有一段关于隐藏字段的明确定义:
Within a class, a field that has the same name as a field in the superclass hides the superclass’s field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super. Generally speaking, we don’t recommend hiding fields as it makes code difficult to read.
从上面这段解释中,我们可以看出成员变量不能像方法一样被重写。当一个子类定义了一个跟父类相同 名字的字段,子类就是定义了一个新的字段。这个字段在父类中被隐藏的,是不可重写的。
在实际的开发中,要尽量避免子类和父类使用相同的字段名,否则很容易引入一些不容易发现的bug
public class JavaDymanic { public static void main(String[] args) { B a = new B(); System.out.println(a.sum()); System.out.println(a.sum1()); System.out.println(a.i); } } class A { public int i = 10; public int sum() { return i + 10; } public int sum1() { return getI() + 10; } public int getI() { return getxx(); } public int getxx(){ return 15; } } class B extends A { public int i = 20; public int sum() { return i + 20; } // public int getI() { // return 20; // } public int getxx(){ return 45; } public int sum1() { return getI() + 20; } }
对于方法
 A/B a = new B(); a.xxx
 如果B有该方法,直接调用调用B的,方法中的变量和方法也先在B中查找
 如果B没有,相当于把父类的方法拉下来,方法中方法现在B中查找,变量在A中查找
对于字段:
 A a = new B(); a.xxx
 通过 a.变量 时,在A中查找
 B a = new B(); a.xxx
 通过 a.变量 时,先在B中查找
②在scala中
在Scala中,子类改写父类的字段,我们称为覆写/重写字段。覆写字段需使用 override修饰
class A { val age : Int = 10 } class B extends A { override val age : Int = 20 } ----测试---- val obj1:A = new B val obj2:B = new B println(obj1.age) //20 println(obj2.age) //20 //这里其实很好理解,我们知道再调用字段age时,反编译查看到的是调用age()方法
覆写字段的注意事项和细节
1.def只能重写另一个def(即:方法只能重写另一个方法)
2.val只能重写另一个val 属性 或 重写不带参数的def
//下面这段代码正确吗?
class A { var name: String = "c" } class B extends A { override val name: String = "q" } 这里我们采用反推的方法,假设没有问题 val b = new B b.name = "s" //这里不会报错,因为调用父类的方法 println(b.name) //结果还是q,而不是s,两个不一致,代码肯定有问题
class A { def sal(): Int = { return 10 }} class B extends A { override val sal : Int = 0 } //注:名字保持一致
3.var只能重写另一个抽象的var属性
//在A中,有一个抽象的字段(属性) //1. 抽象的字段(属性):就是没有初始化的字段(属性) //2. 当一个类含有抽象属性时,则该类需要标记为abstract //3. 对于抽象的属性,在底层不会生成对应的属性声明,而是生成两个对应的抽象方法(name name_$eq) //4.抽象方法不能标记abstract,只要省掉方法体即可。抽象字段/属性就是没有初始值的字段,不能标记abstract abstract class A { var name : String //抽象 var age: Int = 10 } class Sub_A extends A { //说明 //1. 如果我们在子类中去重写父类的抽象属性,本质是实现了抽象方法 //2. 因此这里我们可以写override ,也可以不写。[原因:父类的抽象属性,生成的是抽象方法,因此就不涉及到方法重写的概念,因此override可省略] override var name : String = "" }
六.Scala继承层级一览图

小结:
在scala中,所有其他类都是AnyRef的子类,类似Java的Object。
AnyVal和AnyRef都扩展自Any类。Any类是根节点
Any中定义了isInstanceOf、asInstanceOf方法,以及哈希方法等。
Null类型的唯一实例就是null对象。可以将null赋值给任何引用,但不能赋值给值类型的变量
Nothing类型没有实例。它对于泛型结构是有用处的,举例:空列表Nil的类型是List[Nothing],它是List[T]的子类型,T可以是任何类。

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号