TA的每日心情 | 开心 2021-12-13 21:45 |
---|
签到天数: 15 天 [LV.4]偶尔看看III
|
47.scala编程思想笔记——特征
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/50447596
源码下载连接请见第一篇笔记。
继承可以在现有类的基础上创建新类。这样就无需从头开始重写所有类。
特征是创建类的另一种可选的方式:允许以零碎的方式获取能力,而不是以整块的方式继承所有能力。
特征是小型的逻辑概念,这些基本的功能项使得我们可以很容易地通过混合各种想法来创建类。
特征的定义看起来很像类,但是使用的是trait关键字而不是class.
为了将多个特征组合到一个类中,需要以extends关键字开头,然后使用with关键字添加额外的特征。
例如:
trait Color
trait Texture
trait Hardness
class Fabric
class Cloth extends Fabric with Color
with Texturewith Hardness
class Paint extends Color with Texture
with Hardness
像抽象类一样,特征中的域和方法可以有定义,也可以是抽象的。
例如:
trait AllAbstract {
deff(n:Int):Int
val d:Double
}
trait PartialAbstract {
deff(n:Int):Int
val d:Double
defg(s:String) = s"($s)"
val j = 42
}
trait Concrete {
def f(n:Int)= n * 11
val d =1.61803
}
/* None of these are legal -- traits
cannot be instantiated:
new AllAbstract
new PartialAbstract
new Concrete
*/
// Scala requires "abstract" keyword:
abstract class Klass1 extends AllAbstract
withPartialAbstract
/* Can"t do this -- d and f are undefined:
new Klass1
*/
// Class can provide definitions:
class Klass2 extends AllAbstract {
def f(n:Int)= n * 12
val d =3.14159
}
new Klass2
// Concrete"s definitions satisfy d & f:
class Klass3 extends AllAbstract
with Concrete
new Klass3
class Klass4 extends PartialAbstract
with Concrete
new Klass4
class Klass5 extends AllAbstract
withPartialAbstract with Concrete
new Klass5
trait FromAbstract extends Klass1
trait fromConcrete extends Klass2
trait Construction {
println("Constructor body")
}
class Constructable extends Construction
new Constructable
// Create unnamed class on-the-fly:
val x = new AllAbstract with
PartialAbstract with Concrete
单独的特征不能实例化的,因为没有全功能的构造器。
Abstract类可以继承自特征。
特征可以继承自其他特征,如下:
trait Base {
def f ="f"
}
trait Derived1 extends Base {
def g ="17"
}
trait Derived2 extends Derived1 {
def h ="1.11"
}
class Derived3 extends Derived2
val d = new Derived3
d.f
d.g
d.h
组合特征时,可能会将具有相同签名的两个方法混合在一起。
如果方法或域的签名产生冲突,那么需要人工解决这种冲突。
例如:
import com.atomicscala.AtomicTest._
trait A {
def f = 1.1
def g ="A.g"
val n = 7
}
trait B {
def f = 7.7
def g ="B.g"
val n = 17
}
object C extends A with B {
override deff = 9.9
override valn = 27
override defg = super[A].g + super[B].g
}
C.f is 9.9
C.g is "A.gB.g"
C.n is 27
即使特征域和方法还未定义,也可以在计算机中使用它们:
import com.atomicscala.AtomicTest._
trait Framework {
val part1:Int
defpart2:Double
// Evenwithout definitions:
deftemplateMethod = part1 + part2
}
def operation(impl:Framework) =
impl.templateMethod
class Implementation extends Framework {
val part1 =42
val part2 =2.71828
}
operation(new Implementation) is 44.71828
在基类类型中定义一个操作,使它依赖于将在导出类中定义的部分代码,通常称为模板方法模式。
有些面向对象语言支持多重继承,以便组合多各类。特征通常是一种更好的解决方式。如果需要在类和特征之间做出选择,应该优先选择特征。
|
|