Scala中的抽象类与特征
Scala中的抽象类与特征抽象类Scala的抽象类跟Java的一样,不能被实例化。其中一些特性也与Java的抽象类非常类似。
object AbstractScala {
def main(args: Array[String]): Unit = {
val cat = new Cat("小小")
cat.cry
}
}
abstract class Animal(name:String){
var kind:String //抽象field
def cry //抽象方法
}
class Cat(name:String) extends Animal(name){
override var kind: String = "猫"
override def cry: Unit = println(kind + "["+name+"]" + ":喵!!")
}
抽象类型Scala 中的类型成员也可以是抽象的。 trait Foo {
type T;
val x: T;
def getX: T = x
}
println((new Foo{type T = Int; val x = 123}).getX)
println((new Foo{type T = String;val x = "hello phoebe"}).getX)
/* 123 hello phoebe */
trait(特征)trait的字面意思是特质或者特征。它的意义和java,c#中接口很类似,但java中(implement)接口方法是不能有具体的实现,同时接口也不能继承类,而scala的trait是能有具体实现也能被继承的类。
import java.util.Date
trait Logger {
val time: Long = new Date().getTime
val method: String //抽象字段 类在继承此trait时必须覆盖抽象time字段,提供具体的值
def info(msg: String)
def error(msg: String): Unit = {}
def warning(msg: String): Unit = {}
}
trait ImpError extends Logger {
override def error(msg: String) = println(time + "->>>" + method + "->>>" + msg)
}
trait ImWarning extends Logger {
override def warning(msg: String) = println(time + "->>>" + method + "->>>" + msg)
}
class ConCreateLogger(m: String) extends Logger with Cloneable with ImWarning {
val method: String = m //实现父类的抽象field
def info(msg: String): Unit = println(time + "->>>" + method + "->>>" + msg)
}
object TraitScala {
def main(args: Array[String]): Unit = {
val log = new ConCreateLogger("hello")
log.info("1")
log.error("2")
log.warning("3")
val log2 = new ConCreateLogger("say") with ImpError
log2.info("4")
log2.error("5")
log2.warning("6")
}
}
/* 1516984736844->>>hello->>>1 1516984736844->>>hello->>>3 1516984737232->>>say->>>4 1516984737232->>>say->>>5 1516984737232->>>say->>>6 */
在trait中覆盖抽象方法在trait中,是可以覆盖父trait的抽象方法的。 /** * 下面这个例子基于trait的AOP(Aspect-oriented programming)代码实战 * 也就是基于trait 调用链方式 */
trait DoAction {
def action
}
trait AopBefore extends DoAction {
abstract override def action = {
println("调用前执行-----------")
super.action
println("调用后执行-------------")
}
}
class Work extends DoAction {
override def action: Unit = println("Work!")
}
object TraitScala {
def main(args: Array[String]): Unit = {
//其实就是使用了trait调用链的特性
val w = new Work with AopBefore
w.action
}
}
/* 调用前执行----------- Work! 调用后执行------------- */
类中的apply()在 Scala 的类中,apply() 可以看作是一个语法糖,它分为两种方式:object和class中的用法。 常见的 apply() 用法借用一个经典的例子。 class Foo{}
object FooMaker {
def apply() = new Foo
}
object Demo {
def main(args: Array[String]): Unit = {
val newFoo = FooMaker()
// 在调用 FooMaker() 时,触发了apply(),所以生成了一个新的Foo对象。
}
}
class Bar {
def apply(): Unit = println("this is bar")
}
object Demo {
def main(args: Array[String]): Unit = {
val bar = new Bar
println(bar())
bar()
// 在调用bar()时,触发了apply(),打印了this is bar
}
}
/* this is bar () this is bar */
object类是单例,不能进行new的实例化。在调用类名()时,便会触发调用该object中的apply()。如果object类中没有apply(),这样调用会报错。 scala> object FooMarker2 {
| def apply2() = new Foo
| }
defined object FooMarker2
scala> val newFoo2 = FooMarker2()
<console>:13: error: FooMarker2.type does not take parameters
val newFoo2 = FooMarker2()
在类中,创建 scala> class Bar2 {
| def apply2() = println("this is bar2")
| }
defined class Bar2
scala> val bar2 = new Bar2
bar2: Bar2 = Bar2@7f416310
scala> bar2()
<console>:14: error: Bar2 does not take parameters
bar2()
^
伴生类和伴生对象中的apply()class ApplyTest {
def apply() = println("This is called by class!")
def haveATry: Unit = {
println("have a try on apply")
}
}
object ApplyTest {
def apply() = {
println("This is called by companion object")
new ApplyTest
}
}
object ApplyOperation {
def main(args: Array[String]) {
val a1 = ApplyTest() //object 的 apply() 使用
a1.haveATry
a1() // class 中 apply()使用
println("------------------")
val a2 = new ApplyTest
a2.haveATry
a2() // class 中 apply()使用
}
}
/* This is called by companion object have a try on apply This is called by class! ------------------ have a try on apply This is called by class! */
最后,除了在类中可以使用apply(),在function中也可以使用apply(),因为在 Scala 中函数即对象,后面的笔记会进行总结。 类中的update()
class User(var name:String,var password:String) {
def update(name:String,password:String): Unit = {
println(s"changing use of $name and $password")
this.name = name
this.password = password
}
}
object Demo {
def main(args: Array[String]): Unit = {
val phoebe = new User("phoebe","123456")
println(phoebe.password)
phoebe.update("phoebe","abcdefg")
println(phoebe.password)
phoebe("phoebe") = "123456"
println(phoebe.password)
}
}
/* 123456 changing use of phoebe and abcdefg abcdefg changing use of phoebe and 123456 123456 */
在这里,phoebe.update(“phoebe”,”abcdefg”) 和 phoebe(“phoebe”) = “abcdefg” 这两句话是等价的。前一种方法比较中规中矩,后一种方法更加简洁。 参考资料
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |