scala高级类型
Posted 拱头
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala高级类型相关的知识,希望对你有一定的参考价值。
泛型
泛型相关类
ClassTag
这个类就是泛型类的类型。
泛型类在实例化的时候一定要具体指名泛型类型,泛型在编译的时候信息是抹去的,就会存在以下问题:
def mkArray[T](elem:T*) = Array[T](elem:_*)//编译阶段会报错
上面这句在编译的时候是报错的,因为Array[T]没有指定类型,但是我们有时候要这么写代码怎么办呢?这时候就要用到ClassTag,ClassTag会在编译阶段将泛型的信息保存下来:
def mkArray[
T
:ClassTag](elem:
T*) =
Array[
T](elem:_*)
以上这样定义就没有问题 Manifest 这个类很少用。现在知道的用法和上面的相似 |
>: 和 <:
以上两个符号用来界定泛类型的上下界:
//定义了泛类型的上界(父类) class Pair[ T <: Comparable[ T]]( val first: T, val second: T) def bigger = if(first.compareTo(second) > 0) first else second class Pair_Lower_Bound[ T]( val first: T, val second: T) //定义了泛类型的下界(子类) def replaceFirst[ R >: T](newFirst: R) = new Pair_Lower_Bound[ R](newFirst,second) object Type_Variables_Bounds def main(args: Array[ String]) val pair = new Pair( "Spark", "Hadoop") println(pair.bigger) |
<% 和 >%
以上两个符号称作视图界定
//class Pair_NotPerfect[T <: Comparable[T]](val first:T,val second:T) // def bigger = if(first.compareTo(second) > 0) first else second // class Pair_NotPerfect[ T <% Comparable[ T]]( val first: T, val second: T) def bigger = if(first.compareTo(second) > 0) first else second object View_Bounds def main(args: Array[String]) val pair = new Pair_NotPerfect(2,3) //Int -> RichInt println(pair.bigger) 注意:要是黄底的部分没有注释掉,使用黄底部分的定义的话,下面黄底的部分是会报错的。因为Int类型并没有实现Comparable,但是使用<%后就会正确了,因为使用试图界定会将隐式转换传进来,如果隐式转换有几成Comparable就行了,就像这里的Int转成RichInt了。 |
<:<
以下两段代码的作用基本相同:
def
rocky[T](i:T)(implicit en:T<:<java.io.Serializable): Unit =
println( "aaaaa!!!!") def rocky[T<:java.io.Serializable](i:T): Unit = println( "aaaaa!!!!") |
+T 和 -T
协变和逆变,
协变:就是E是T的子类型那么A[E]是A[T]的子类型
逆变:就是E是T的子类型那么A[T]是A[E]的子类型
class Person
class Student extends Person class C[ +T]( val arg: T) trait Friend[ -T] def makeFriend(somebody: T) object Vaniance def makeFriendWithYou(s:Student,f:Friend[Student]): Unit = f.makeFriend(s) def main(args: Array[ String]) val value :C[Person] = new C[Student](new Student) 注意一下:java不能再泛型定义的时候界定协变和逆变,但是可以在使用的时候界定: // List<? extends Object> list = new ArrayList<String>() val list: List[_<:Any] = List[ String]() 注销掉的是java的代码,和下面没有注释的scala代码同义 |
单例类型v.type: this.type的使用: 注意以下区别: class Animal def breathe = this
class Cat extends Animal def eat = this
object Singleton_Types
def main(args: Array[ String])
val cat = new Cat
cat.breathe .eat //这里报错了,因为breathe返回的类型是Animal,Animal中没有定义eat
解决以上问题,使用以下代码: class Animal def breathe:this.type = this
class Cat extends Animal def eat:this.type = this
object Singleton_Types
def main(args: Array[ String])
val cat = new Cat
cat.breathe. eat
类型投影: 类型投影就是类中的类: class Outer
private val x = 10
class Inner
private val y = x + 10
投影类型会有一个路径问题,还是使用上面定义的代码: val outer1 = new Outer
val outer2 = new Outer
var inner = new outer1.Inner inner = new outer2.Inner //outer1.Inner和outer2.Inner不是同一个类型 标红的地方报错,因为outer1.Inner和outer2.Inner由于路径不同,并不是同一个类型。可以用Outer#Inner解决这个问题。 val o1 = new Outer
val o2 = new Outer var i: Outer#Inner = new o1.Inner //前面用的Outer#Inner表示任何Outer的Inner i = new o2.Inner
结构类型: type关键字:
用法一:
type
str =
String var a: str = _ a = "aaaa" 就是个类型加一个别名。 |
用法二:
class Structuralclass
def open() =
println(
"A class instance Opened!!!")
object Structural_Type def main(args: Array[ String]) type X = def open():Unit def init(rec: X) = rec.open() //带open()方法的class init( new Structuralclass) //带open()方法的object object A def open() = println( "A single object Opened!!") init(A) //使用匿名类 init( new def open() = println( "Opened again!!!")) 这个用法的好处就是,我可以将所有含有open()方法的类型都传给init(),各个类型之间不需要有任何继承关系 |
中置类型: 带两个值得泛型类可以使用中置表达式: 例子: class Infix_Type[ A, B]
val infix: Int Infix_Type String = null val infix1: Infix_Type[Int, String] = null 上面2,3两行代码的作用是相同的,可以看到黄底的地方使用了中值表达式。
自身类型: 这里有两种用法
设置this的别名:
class Self
self => //这一行的意思是定义self为this的别名 val tmp= "Scala" def foo = self. tmp + this. tmp 这么做在使用内部类调用外部类的时候就会很方便: class Outer outer => val v1 = "Spark" class Inner println(outer. v1) |
限制类型可以混入的特质:
看以下代码:
trait Logged
def log(msg: String) trait LoggedException extends Logged this: Exception=> //只能混入Exception的子类 def logException() log(getMessage()) //这里使用到的getMessage()方法是Exception中的方法 这个时候我们需要混入LoggedException特质,如果使用以下代码会报错: val ex = new JFrame( "ClassNotFoundException") with LoggedException override def log(msg: String): Unit = println(msg) 因为JFrame不是Exception的子类,不能混入LoggedException,只有Exception的子类才能混入,例如下面这样: Exception的子类 val ex = new ClassNotFoundException( "ClassNotFoundException") with LoggedException override def log(msg: String): Unit = println(msg) |
以上是关于scala高级类型的主要内容,如果未能解决你的问题,请参考以下文章