你见过这样的函数定义吗?
def square[T : Numeric](n: T) = implicitly[Numeric[T]].times(n, n)
这篇博客将揭示Scala的类型系统的众多细节
1. 总括
The more you know about Scala’s type system, the more information you can give the compiler
你对类型系统了解越多,就能给编译器越多的信息
When using a type system, it’s best to think of it as an overprotective father. It
will constantly warn you of problems or prevent you from doing things altogether.
The better you communicate with the type system, the less restrictive it becomes.
But if you attempt to do something deemed inappropriate, the compiler will warn
把类型系统看作一个过度保护你的父亲,在你做不合适的事时就不停地警告你
2. 什么是类型?
对于编译器而言,类型意味着一组信息:一个变量应该是那个类的实例,对这个变量可以进行哪些操作
3. 创建类型的方法
(1) 定义 class, trait, object
(2) 使用type关键字
4. 类型的名字
如果通过定义class或trait定义类型,类型的名字就是class或trait的名字。如果是object,类名并没有太多意义,编译器有生成类名的一套规则
package ch6 object TestType { println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet object T T.getClass //> res0: Class[?0] = class ch6.TestType$$anonfun$main$1$T$2$ }
5. 那么object最为函数的参数时如何声明类型呢? object名字.type
object Obj { val ss = 22 } def f(obj: Obj.type ):Unit = println(obj.ss) f(Obj)
6. 对内部类的引用有两种方式 , hash(#)和dot(.),且看下面的例子
package ch6 object Test2 { println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet class Outer { trait Inner def y = new Inner {} def foo(x: this.Inner) = null def bar(x: Outer#Inner) = null } val x = new Outer //> x : ch6.Test2.Outer = [email protected] val y = new Outer //> y : ch6.Test2.Outer = [email protected] x.y //> res0: ch6.Test2.x.Inner = [email protected] //| x.foo(x.y) //> res1: Null = null x.foo(y.y) //type mismatch; found : ch6.Test2.y.Inner required: ch6.Test2.x.Inner x.bar(y.y) //> res2: Null = null }
对象.类型 把类型绑定到了一个特殊的对象上
#的要求就没有那么严格了
7.type关键字的用法1
type AbstractType //定义一个抽象类型(不是抽象类)
type ConcreteType = SomeFooType //定义一个具体类型
type ConcreteType2 = SomeFooType with SomeBarType // 定义一个组合型的具体类型
8.type关键字用法2: 定义带结构的type
方法f的参数是一个带有方法g的类型。 要表达这样的含义就要用到structural type。
通常情况下,一个对象是什么类型要从它是什么class,它继承了什么class或它带来那些trait。
但是这样的语义并不是完全的。比如生活中我们常用这样的语句表达一个类型:带有水壶架的自行车。如果自行车没有继承水壶架类,或根本没有水壶架类,那么这样的意思在scala中该怎么表达呢?
package ch6 object Test3 extends App{ object Resources { type Resource = { def close(): Unit } def closeResource(r: Resource) = { r.close() println("resource closed") } } Resources.closeResource(System.in) }
Resource就是我们自己定义的一个带close方法的类型