Scala面向对象
(一)类
class语法详解
1 在Scala中,类并不用声明为public类型的(默认就是public)
2 Scala源文件中可以包含多个类,所有这些类都具有共有可见性
3 调用无参方法时,可以加(),也可以不加;如果方法定义中不带括号,那么调用时就不能带括号
访问权限
Java 中的访问控制权限,同样适用于 Scala,
可以在成员前面添加private/protected关键字来控制成员的可见性。
但在scala中,没有public关键字,
任何没有被标为private或protected的成员都是公共的
@BeanProperty:
JavaBeans规范定义了Java的属性是像getXXX()和setXXX()的方法。
许多Java工具都依赖这个命名习惯。
为了Java的互操作性。将Scala字段加上@BeanProperty,
getter和setter方法会自动生成。
自定义getter/setter
如果自己手动创建变量的getter和setter方法需要遵循以下原则:
- 字段属性名以_作为前缀,如:_leg
- getter方法定义为:def leg = _leg
- setter方法定义时,方法名为属性名去掉前缀,并加上后缀,后缀是:leg_=
(二)对象object
1.作为程序入口-语法详解:
在 Scala 中和Java一样也必须要有一个 main 方法作为程序的入口,
而且必须定义在 object 中,除了自己实现 main 方法之外,
还可以通过继承 App Trait(类似接口)来实现
● 编写object继承App
● 将需要写在 main 方法中运行的代码,直接作为object的constructor代码
● 使用 args 接收传入的参数
2.作为工具类-语法详解:
在Scala中没有静态方法和静态字段,但是可以使用object来达到同样的目的。
可以类比与Java中的工具类
3.作为伴生对象-和伴生类的相互访问-语法详解
● 类比Java 在Java中,经常会有一些类,同时有实例成员又有静态成员。
● Scala中的伴生对象在scala中,要实现类似的效果,可以使用伴生对象来实现。一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类
1 伴生对象必须要和伴生类一样的名字
2 伴生对象和伴生类在同一个 Scala 源文件 中
3 伴生对象和伴生类最大特点是,可以相互访问,包括private属性
● 注意:
如果某个成员的权限设置为 private[this],表示只能在当前类中访问。伴生对象也不可以访问
4.pply和updata方法-语法详解
● apply方法
我们之前使用过这种方式来创建一个Array对象:val a = Array(1,2,3,4) 这种写法非常简便,可以不使用 new class/class() 的方式,是直接使用 class()就可以创建对象 ,它的底层其实是隐式的调用了伴生对象的 apply 方法
● update方法
另外在进行数组赋值的时候,之所以没有采用Java中的方括号myStrArr[0],而是采用圆括号的形式,myStrArr(0), 是因为存在Array伴生对象中存在update方法。
● 注意
伴生对象名.apply ==> 执行 object 中的apply方法
实例对象 .apply ==> 执行 class 中的apply方法
(三)继承
● extends
1 Scala 中的继承与 Java 一样也是使用 extends 关键字;
2 子类可以继承或覆盖父类的 field 和 method , 也可以实现子类特有的 field 和method
● override
Scala 中,如果子类要覆盖父类中的字段或方法,要使用 override 关键字;
● super
在子类中要调用父类中被覆盖的方法,要使用 super 关键字, 显示的指出要调用的父类方法。
● 注意
1 final修饰的类不能被继承
2 final修饰的字段或方法不能被覆盖
3 修饰的 field 和 method 不可以被子类继承
4 val字段使用 override 关键字覆盖
5 var字段不能使用override 关键字重新赋值(注意不是重新定义)
6 override 关键字可以帮助开发者尽早的发现代码中的错误,如方法名拼写错误,参数错误等等, 所以建议覆盖时加上override关键字;
类型判断、转换、获取
● isInstanceOf 和 asInstanceOf
obj.isInstanceOf[XX类名]
判断 obj 是否为 XX 类型的实例(判断对象是否为指定类以及其子类的实例)
类似于 Java 中的: obj instanceof xx
obj.asInstanceOf[XX类名]
把 obj 转换成 XX 类型的实例
类似于 Java 中的: (XX)obj
● 注意:
如果对象是 null,
isInstanceOf 一定返回 false,
asInstanceOf 一定返回 null;
● getClass 和 classOf
obj.getClass
可以精确地获取对象的类型
就是Java中的: 对象.getClass
classOf[XX类名]
可以精确的获取类的类型
类似于Java中的: 类名.class
● Scala与Java类型检查和转换类比
Scala Java
obj.isInstanceOf[XX类名] obj instanceof XX类名
obj.asInstanceOf[XX类名] (XX类名)obj
obj.getClass obj.getClass
classOf[XX类名] XX类名.class
调用父类的构造器
1 Scala中每个类都可以有一个主构造器和任意多个辅助构造器,
2 辅助构造器的第一行都必须调用其他辅助构造器或者主构造器代码;
3 子类的辅助构造器是一定不可能直接调用父类的构造器的,只能在子类的主构造器中调用父类的构造器。
4 父类的构造函数已经定义过的字段,子类在使用时, 不需要使用 val/var 来修饰,否则会被认为,子类要覆盖父类的字段
●
抽象类、抽象方法和抽象字段
1 一个类中,如果含有一个抽象方法或抽象字段,就必须使用abstract将类声明为抽象类,该类是不可以被实例化的
2 如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现不同的方法此时,可以将父类中的这些方法编写成只含有方法签名,不含方法体的形式,这种形式就叫做抽象方法
3 如果在父类中,定义了字段,但是没有给出初始值,则此字段为抽象字段
4 抽象类中可以有普通字段和方法
● 注意
在子类中覆盖抽象类的抽象方法时,可以不加override关键字,但建议加上;
重写父类的非抽象方法,必须使用override关键字
(四)Trait
1.trait作为接口封装字段、方法
● trait作为接口
Scala中的trait是一种特殊的概念,与Java中的接口 (interface)非常类似
(Java8中接口的新特性:默认方法、静态方法就抄袭Scala的!)
● 注意:
1 类可以使用extends关键字继承trait
2 注意不是 implement,而是extends , 在Scala中没有 implement 的概念,无论继承类还是trait,统一都是 extends
3 Scala和Java一样不支持多继承类,但是支持多重继承 trait, 使用 with 关键字即可
● 在trait中定义抽象方法
在trait中可以定义抽象方法,类继承后,必须实现抽象方法,可以不使用 override 关键字,建议加上;
● 在trait中定义抽象字段
在trait 中trait也能定义抽象字段,继承 trait 的类,则必须覆盖抽象字段,提供具体的值
● 在trait中定义具体方法
在trait中不仅可以定义抽象方法,还可以定义具体的方法
● 在trait中定义具体字段
此时继承 trait 的子类就自动获得了 trait 中定义的字段,但是这种获取字段的方式与继承 class 的是不同的,如果是继承 class 获取的字段,实际上还是定义在父类中的,如果是继承 trait获取的字段,就直接被添加到子类中了
2.trait继承class-语法详解
trait也可以继承class且会将class中的成员都继承下来
3. 对象混入 trait - 语法详解
1 在实例化对象时可以使用 with 关键字混入某个trait, 这样就可以为该对象动态的添加额外的功能
2 val/var 对象名 = new 类 with 特质
4.trait的构造机制 - 语法详解
1 trait也是有构造代码的,即在trait中,不包含在任何方法中的代码;
2 trait不能有构造器参数,每个 trait 都有一个无参数的构造器 (缺少构造器参数 是trait与类之间主要的差别)
3 继承了trait的子类,其构造机制如下:
-父类的构造函数先执行,即 class 类必须放在最左边;
-trait的构造代码后执行,多个trait从左向右依次执行;
-构造trait时,先构造父 trait,如果多个trait继承同一个父trait,则父trait只会构造一次;
-所有trait构造完毕之后,子类的构造函数最后执行。