scala 面向对象编程
原则1 保持简洁
scala的原则是尽量不产生任何样板代码。所以当声明一个类的成员时,它会自动帮你生成好getter和setter方法,并且就像直接读取和修改成员一样自然。你可能以为正在直接读取某个成员变量,实际上却是在调用该成员变量对应的getter方法。即保持了代码简洁又坚守了单一访问原则。
scala的构造器非常简单,在声明类的同时便同时声明了主构造器,同时还可能声明了内部的字段。当然主构造器的作用是有限的,它就像C++中的构造函数初始化列表,但它可以顺便将列表中的变量一并做了定义。如果需要复杂的构造函数则需要自己提供次级构造器。
对于主构造器的参数,如果附带上了val和var之类的字段,则说明这些字段是类的成员变量,如果没有带上val或者var关键字,则说明这些字段只存在于该类中,但却不是它的一个成员。可以看作为是类的私有成员,我们在构造该类时必须传人它,在类中的方法也可以使用这个参数但是它并没有get方法和set方法。外部也不会知道这个类的存在。
原则2 一切皆对象
scala所有的类都有一个父类型Any
,下面有两个子类AnyVal
和AnyRef
, 分别代表着值类型和引用类型。不像java和C++有原生类型,scala的一切都是对象,都来自同一个根:Any
类型。AnyVal类型是构造在栈上的,AnyRef类型是构造在堆上的。对应着java中的原生类型和Object。
但是对值类型进行包装,添加一些额外的方法,包装的类就会变成引用类型,从而失去在原生类型的良好性能。好在scala提供了一种叫做价值类的东西,可以避免分配在堆上。价值类有一系列的条条框框,最重要的是只能有一个val参数,以及不能有其他变量,只能定义方法,并且价值类只能继承自通用特征。
通常的用法都是使用价值类包装一个AnyVal类型例如Int,String之类。
题外话
继承通常情况下是不好的,多用组合少用继承。
使用继承时许遵守以下原则:
- 一个抽象的基类或trait只被下一层的具体的类继承。
- 具体的子类永远不会再次被继承。除非混入了定义于trait中的其他行为。
- 考虑将行为分离到trait中,然后在类里混入这些trait。