scalaタイプパラメータ

10442 ワード

1、汎用性の本質はパラメトリックタイプであり、(1)Arrayは汎用性パラメータとタイプ変数をその要素のタイプとすることができる.(2)基本タイプのサポート(3)サイト可変性(4)上下境界のサポート,および複数の上界を複合タイプモードとして配置することを宣言する.
import scala.collection.immutable.Queue
class Triple[F,S,T](val first:F,val second:S,val third:T)
object HelloTypeParameterization{
def main(args:Array[String]){
val triple=new Triple(“spark”,3,3.1415)
val bigdata=new Triple[String,String,Char](“Spark”,”Hadoop”,”R”)
val getDate[T](list:List[T])=list(list.length/2)
println(getData(List(“Spark”,”Hadoop”,”R”)))
val f=getData[Int]_
println(f(List(1,2,3,4,5)))
val queue=Queue(1,2,3,4)

}
}

2、javaモデルクラスの上下境界を定義する.タイプの上限または
class User(val userName: String,val age: Int) extends Comparable[User] {
  override def compareTo(o: User): Int = this.age - o.age
}


object OrderingDemo extends App {

  /**
    *     ,  
    *
    * @param u1
    * @param u2
    * @tparam T T   Comparable[T]   
    * @return
    */
  def compare[T <: comparable="" t="" u2:="" int="{" class="hljs-keyword">if (u1.compareTo(u2) == 0) 0 else if (u1.compareTo(u2) > 0) 1 else -1

  }


  val u1 = new User("u1", 18)
  val u2 = new User("u2", 19)

  //  compare(u1,u2) //class User(userName: String, age: Int)  ,     

  println(compare(u1,u2)) //class User(val userName: String,val age: Int) extends Comparable[User]


}

上界
trait Similar {
  def isSimilar(x: Any): Boolean
}
case class MyInt(x: Int) extends Similar {
  def isSimilar(m: Any): Boolean =
    m.isInstanceOf[MyInt] &&
    m.asInstanceOf[MyInt].x == x
}
object UpperBoundTest extends App {
  def findSimilar[T <: similar="" t="" xs:="" list="" boolean="<span" class="hljs-keyword">if (xs.isEmpty) false
    else if (e.isSimilar(xs.head)) true
    else findSimilar[T](e, xs.tail)
  val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3))
  println(findSimilar[MyInt](MyInt(4), list))
  println(findSimilar[MyInt](MyInt(2), list))
} 

下界
case class ListNode[+T](h: T, t: ListNode[T]) {
  def head: T = h
  def tail: ListNode[T] = t
  def prepend[U >: T](elem: U): ListNode[U] =
    ListNode(elem, this)
}
object LowerBoundTest extends App {
  val empty: ListNode[Null] = ListNode(null, null)
  val strList: ListNode[String] = empty.prepend("hello")
                                       .prepend("world")
  val anyList: ListNode[Any] = strList.prepend(12345)
}

3、タイプ制約タイプ同等制約T=:=UテストTタイプがUタイプサブタイプ制約T<:>
object TypeContrains{
def main(args:Array[String]){
//A=:=B
//A<:>
def rocky[T](i:T)(implicit ev:T<: println="" class="hljs-keyword">is short, you need Spark!”)

}
rocky(“Spark”)
}
}

4、タイプシステムClassTag特質消去されたTタイプのクラス情報、実行時のクラス情報、TypeTag特質はTのすべての静的タイプ情報を含む
class A[T]
object Manifest_ClassTag{
def main(args:Array[String]){
def arrayMake[T:Manifest](first:T,second:T)={
val r=new Array[T](2);
r(0)=first;
r(1)=second;
r
}
arrayMake(1,2).foreach(println)

def mkArray[T:ClassTag](elems:T*)=Array[T](elems:_*)
mkArray(42,31).foreach(println)
mkArray(“Hello”,”Spark”,”and you”).foreach(println)


def manif[T](x:List[T])(implicit m:Manifest[T])={
if(m<:<manif[String])
println(“List String”)
else 
println(“Other type”)

}


val m=manifest[A[String]]
println(m)
val cm=classManifest[A[String]]
println(m)
}
}

5、型変Variance scala型変注釈は、型抽象を定義する際に指定し、まずコヒーレントとインバータ(実際には非変もある)について述べる.コヒーレントとインバータは主にパラメトリックタイプの汎化問題を解決するために用いられる.パラメトリックタイプのパラメータ(パラメータタイプ)は可変であるため、2つのパラメトリックタイプのパラメータが継承関係(汎化可能)である場合、パラメトリックタイプも汎化できるのではないでしょうか.Javaではこの場合は一般化できないが,Scalaはコヒーレント,インバータ,非変動の3つの選択を提供する.以下に3つのケースの意味を述べ,まずパラメトリック特徴Queueがあると仮定すると,以下の3つの定義が可能である.1)trait Queue[T]{}これは非変態である.この場合、タイプSがタイプAのサブタイプである場合、Queue[S]は、Javaと同様に、Queue[A]のサブタイプまたは親タイプとは考えられない.
2)trait Queue[+T]{}これはコヒーレントな場合である.この場合、タイプSがタイプAのサブタイプである場合、Queue[S]はQueue[A]のサブタイプであると考えられ、つまりQueue[S]はQueue[A]に一般化される.すなわち,パラメトリックタイプの汎化方向はパラメータタイプの方向と一致するので,コヒーレントと呼ぶ.
3)trait Queue[-T]{}これは逆の場合である.この場合、タイプSがタイプAのサブタイプである場合、Queue[A]は逆にQueue[S}のサブタイプと考えられる.すなわち、パラメータ化されたタイプの汎化方向はパラメータタイプの方向とは逆であるため、逆と呼ぶ.
次に例を見ます.
trait Function[-Arg,+Return]{ 
def apply(arg:Arg):Return 
} //defined trait Function 
val foo = new Function[Any,String]{
 override def apply(arg:Any) :String = s"Hello ,I received a $arg"
 } //foo: Function[Any,String] = $anon$1@72dda13a 
val bar:Function[String,Any] = foo 
//bar: Function[String,Any] = $anon$1@72dda13a
 foo("test") //res0: String = Hello ,I received a test 
bar("test") //res1: Any = Hello ,I received a test 

1まずFunctionの定義を見てみましょう.パラメータArgの位置が逆に定義されています.これは、あるタイプが必要なときに親タイプ、すなわち老子が息子を交換し、戻り値タイプがコヒーレントに定義されていることを意味します.これは、あるタイプが必要なときに彼の子タイプを置換することです.白話は息子が老子2を交換してfooの定義を見てみましょう.彼のパラメータタイプはAnyで、戻り値タイプはStringなので、彼のapply方法はAnyタイプのパラメータを受信して、Stringタイプの結果を返します.これはfoo(「test」)がStringタイプのres 0 3を返している理由です.barの定義を見てみましょう.パラメータタイプはStringです.戻り値タイプはAnyなのでbarを呼び出すことができればStringに入る必要があり、結果はAny、つまりbar("test")がAnyである理由4でなぜそのval bar:Function[String,Any]=fooと書くことができるのかは型変に関係しており、Functionパラメータ位置が逆変するためStringが必要な場合は彼の老子Anyで置き換えることができ、fooタイプのパラメータ位置はちょうどAnyであり,同理戻り値タイプコヒーレンスであり,必要なのはAnyであり,Stringへの伝達も当然であるため,コンパイルにより結果を生成することができる.