scala里的类型,除了在定义class
,trait
,object
时会产生类型,还可以通过type
关键字来声明类型。
type相当于声明一个类型别名:
scala> type S = String
defined type alias S
上面把String类型用S代替,通常type用于声明某种复杂类型,或用于定义一个抽象类型。
场景1 用于声明一些复杂类型,比如下面声明一个结构类型
scala> type T = Serializable {
| type X
| def foo():Unit
| }
defined type alias T
这个结构类型内部也允许通过type来定义类型,这里对X没有赋值表示X是一个抽象类型,需要子类型在实现时提供X具体的类型。下面是一个T类型的具体实例:
scala> object A extends Serializable{ type X=String; def foo(){} }
scala> typeOf[A.type] <:< typeOf[T]
res19: Boolean = true
场景2 用于抽象类型
scala> trait A { type T ; def foo(i:T) = print(i) }
scala> class B extends A { type T = Int }
scala> val b = new B
scala> b.foo(200)
200
scala> class C extends A { type T = String }
scala> val c = new C
scala> c.foo("hello")
hello
呃,感觉应该先abstract type member后type alias,毕竟前者是功能性的,后者只是sugar。
这里如何解释?
scala> type S = String
defined type alias S
scala> typeOf[String]
res14: reflect.runtime.universe.Type = String
scala> typeOf[S]
res15: reflect.runtime.universe.Type = S
scala> typeOf[S] == typeOf[String]
res16: Boolean = false
你这是两个对象的引用比较,要证明这两个类型是否相同用:
typeOf[S] =:= typeOf[String]
有道理。
应该用getClass试试。
typeOf[T] 是一个Type对象。
不过 typeOf[S] =:= typeOf[String]这个也是不对的哦, 因为 =:= 的意思是 =:=[X, Y] , 产生一个新的类型。
scala> typeOf[S] =:= typeOf[String]
:9: error: not found: value typeOf
typeOf[S] =:= typeOf[String]
^
:9: error: not found: value typeOf
typeOf[S] =:= typeOf[String]
^
scala> type S = String
defined type alias S
scala> val k = new S
k: String = “”
scala> val t = new String
t: String = “”
scala> k.getClass
res0: Class[_ t.getClass
res1: Class[_ <: String] = class java.lang.String
用 =:=[A, B] 可以证明A,B两个类型是否等价的,B是A的别名的话,它两是等价的。
但A, B仍是两种类型,它们的type对象是不同的。
scala> import scala.reflect.runtime.universe.typeOf
import scala.reflect.runtime.universe.typeOf
scala> type S = String
defined type alias S
scala> typeOf[S] =:= typeOf[String]
res0: Boolean = true
场景2跟使用泛型, 哪个好一点?
我来补充一下泛型的情形,根据个人喜好做选择
trait A[T]{
// 此时不再有type,取而代之的是泛型参数T
def foo(I: T):Unit = println(i)
}
// 本例中指定T为Int类型
// 继承时指定T的具体类型
class B extends A[Int]
val b = new B
b.foo(200)
// 若不指定具体类型,则继承时保留泛型参数T
class B[T] extends A[T]
// 在实例化时指定类型为Int
val b = new B[Int]
b.foo(200)
// 本例中指定T为String类型
// 继承时指定T的具体类型为String
class C extends A[String]
val c = new C
c.foo(“hello”)
// 在实例化时指定具体类型为String
class C[T] extends A[T]
val c = new C[String]
c.foo(“hello”)
// 总结:type提供了语法糖,将泛型作为成员变量,将指定具体类型这一操作延迟到继承和实例化阶段完成,如果不使用type,则必需在类型中携带泛型参数T,直到泛型参数T被明确指定为具体类型为止