記事のディレクトリ
ジェネリック
使用例
def test={
//应用1
val msg = new IntMessage(1)
println(msg)
val msg2 = new StringMessage[String]("class")
println(msg2)
//应用2
val class01 = new EnglishClass[String,String,String]("春季","大数据","初级")
val class02 = new EnglishClass[String,String,Int]("春季","大数据",1)
//应用3
val list1 = List("hello","tom");
println(midList[String](list1))
val list2 = List(1,2);
println(midList[Int](list2))
}
//应用案例1
abstract class Message[T](s:T){
def get():T ={
s
}
}
class IntMessage[Int](s:Int) extends Message{
}
class StringMessage[String](s:String) extends Message{
}
//应用案例2
class EnglishClass[A,B,C](val season:A,val name:B,val cType:C){
}
//应用案例3
def midList[E](l:List[E]):E={
l(l.length/2)
}
タイプ制約の上限と下限
上界
Javaのジェネリックスは、extendsキーワードを使用して、特定のタイプがAのサブタイプであることを示しています。この形式が上限になり、構文は次のようになります。
<T extends A>或<? extends A>
Scalaのジェネリックスは、特定のタイプがAのサブタイプであることを示しており、<:を使用するための構文は次のとおりです。
[T<:A] 或 [_<:A]
上限の適用は、
IntとFloatなどを直接比較するための一般的なクラスで記述できます。Comparableインターフェイスの値が実装されています。コードは次のとおりです。
def test={
//传统方式
val comparaInt = new ComparaInt(10,20)
println(comparaInt.greater)
//上限 方式
//这种方式直接报错,因为 scala 的 Int 类型没有实现 Comparable
// val commonCompare1 = new CommonCompare(10,20)
// println(commonCompare1.greater)
//传入 Integer 得到正常结果 20
val commonCompare2 = new CommonCompare(Integer.valueOf(10),Integer.valueOf(20))
println(commonCompare2.greater)
//传入 Int 得到正常结果 20
//这是因为 predef 中定义了隐式转换,这里声明了 需要 java.lang.Integer 传入了 Int 编译器自动转换
val commonCompare3 = new CommonCompare[java.lang.Integer](10,20)
println(commonCompare3.greater)
//使用 视图的时候 可以自动进行 隐式转换 而不必 声明需要 java.lang.Integer
val commonCompare4 = new CommonCompare2(10,20)
println(commonCompare4.greater)
}
//传统方法
class ComparaInt(n1:Int,n2:Int){
def greater = if(n1>n2) n1 else n2
}
//泛型方法
class CommonCompare[T <:Comparable[T]](obj1:T,obj2:T){
def greater = if(obj1.compareTo(obj2)>0)obj1 else obj2
}
//泛型方法 视图 方式
class CommonCompare2[T <%Comparable[T]](obj1:T,obj2:T){
def greater = if(obj1.compareTo(obj2)>0)obj1 else obj2
}
下限
JavaジェネリックスでタイプAの親タイプとして特定のクラスを識別するには、次のようにsuperキーワードを使用します。
<T super A> 或<? super A>
Scalaでは、下限または下限は次のように>:キーワードを使用します。
[T >:A]或[_>:A]
例
def test={
//满足下界的约束 Hello Earth
sound(Seq(new Earth ,new Earth)).map(_.sound())
//满足下界的约束 Hello Animal
sound(Seq(new Animal,new Animal)).map(_.sound())
//满足下界的约束 Hello Bird 这里虽然不是 Animal的父类也可以满足下界的约束 实际上是将 Bird 转换成了Animal类型
sound(Seq(new Bird,new Bird)).map(_.sound())
//如下代码编译执行都没有问题 因此不能用上界的思路去推导,是否满足
sound(Seq(new Moon,new Moon))
}
def sound[T>:Animal](things:Seq[T])=things
class Earth{
def sound(){
println("Hello Earth")
}
}
class Animal extends Earth {
override def sound(){
println("Hello Animal")
}
}
class Bird extends Animal {
override def sound(){
println("Hello Bird")
}
}
class Moon{
def sound(){
println("Hello Moon")
}
}
下限の使用の概要任意の型を下限に渡すことができます。渡されたものがTのサブクラスの場合、T型に従って処理され、Tに関係のないクラスはオブジェクトとして処理されます。 。
つまり、下限はパラメータを自由に渡すことができますが、処理方法は異なります。
定義を表示
つまり、ビュー定義は自動的に暗黙的な変換を使用してターゲットタイプに変換し、純粋に下限のメソッドは自動的に暗黙的な変換を使用しませんが、ビュー定義は
文法になります:[T <%A]または<? <%A>:定義されているかどうかを示します入力パラメータタイプとAタイプの間の暗黙的な変換の場合、暗黙的な変換が自動的に呼び出され、入力パラメータがAタイプに
変換されます。例:暗黙的な変換を自分で記述します。そして、Personオブジェクトの年齢をビュー定義と比較します。
//创建隐式转换,自动将 person 对象转换为Ordered的对象
implicit def personToOrderedPerson(p:Person3) = new Ordered[Person3]{
override def compare(that: Person3): Int = {
p.age-that.age
}
}
def test={
val p1 = new Person3("jim",10)
val p2 = new Person3("tom",12);
import impli.MyImplicit._
//创建时自动
val compareComm3 = new CompareComm(p1,p2)
println(compareComm3.getter2)
}
class Person3(val name:String,val age:Int){
override def toString: String = this.name+" "+this.age
}
class CompareComm[T<% Ordered[T]](obj1:T,obj2:T){
//这种写法可以使用隐式转换
def getter2 = if(obj1.compareTo(obj2)>0) obj1 else obj2
}
// class CompareComm2[T<: Ordered[T]](obj1:T,obj2:T){ //这种写法不能使用隐式转换
// def getter2 = if(obj1.compareTo(obj2)>0) obj1 else obj2
// }
コンテキスト化
ビュー境界と同様に、コンテキスト境界(コンテキスト境界)も暗黙的なパラメーターの構文糖衣です。「コンテキスト境界」の概念は、文法上の便宜のために導入されています。
例:コンテキストバウンド+暗黙のパラメーターを使用して、2人の年齢を比較します
//定义隐式值
implicit val personComp= new Ordering[Person4]{
override def compare(x: Person4, y: Person4): Int = {
x.age-y.age
}
}
class Person4(val name:String,val age:Int){
override def toString: String = this.name+" "+this.age
}
//类构造函数的参数可以放在 两个括号中
//class TT (val name:String)(val age:Int){}
//方式一 构造参数中使用隐式转换
//构造函数的参数可以放在两个括号中
// class CompareComm[T:Ordering](obj1:T,obj2:T)(implicit comparator:Ordering[T]){
class CompareComm[T:Ordering](obj1:T,obj2:T)(implicit comparator:Ordering[T]){
def greater = if(comparator.compare(obj1,obj2)>0)obj1 else obj2;
}
//方式二 将隐式转换放在方法内
class CompareComm2[T:Ordering](obj1:T,obj2:T){
def greater ={
def f1 (implicit comparator:Ordering[T]) ={
comparator.compare(obj1,obj2)
}
if(f1> 0) obj1 else obj2
}
}
//方式三 使用 implicitly 最简单
class CompareComm3[T:Ordering](obj1:T,obj2:T){
def greater ={
//这句话本身就是隐式转换,获取到personComp
implicit val comparator =implicitly[Ordering[T]]
if(comparator.compare(obj1,obj2)> 0) obj1 else obj2
}
}
def test={
val p1 = new Person4("jim",10)
val p2 = new Person4("tom",12);
//方式一
val comp = new CompareComm[Person4](p1,p2)
println(comp.greater)
//方式二
val comp2 = new CompareComm2[Person4](p1,p2)
println(comp2.greater)
//方式三
val comp3 = new CompareComm3[Person4](p1,p2)
println(comp3.greater)
}
共変性、反変性、不変性
リスト[T]などのベルトタイプのジェネリックパラメーターの場合、AとサブタイプBがリスト[B]を満たしている場合はリスト[A]サブタイプであり
、ベルトの共変(共変)と呼ばれますリストなどのジェネリックパラメーターのタイプ[T]、AとそのサブタイプBについて、List [A]がList [B]のサブタイプであることが満たされる場合、それは反変と呼ばれます。
それが共変でも反変でもない場合、それは不変です。たとえば、List [T]の場合、AとそのサブタイプBの場合、List [A]とList [B]の間に親子関係はありません
。Javaのすべてのジェネリック型は不変です。つまり、ListとListは不変ではありません。親子関係があります。
Scalaでは、型を定義するときに、文法的な定義を通じて共変または反変として宣言できます。宣言を行わない場合、デフォルトは変更されません。
例:
List [+ T]は、次の場合に共変として定義されます。typeが宣言されているため、List [String]はListです。[Any]
List [-T]のサブクラスは、型宣言で反変として定義されているため、List [Any]はList [String]のサブクラスの例です。
def test={
//协变
//由于 协变 Tclass[Super] 是Tclass[Sub] 的父类 所以 可以直接赋值不报错
val t2:Tclass[Super] = new Tclass[Sub](new Sub())
//同理该行报错 父类型变量不能赋值给子类型
// val t3:Tclass[Sub] = new Tclass[Super](new Super())
//逆变
//由于 协变 Tclass[Super] 是Tclass[Sub] 的子类类 父类不能赋值给子类 所以该行报错
// val t4:Tclass2[Super] = new Tclass2[Sub](new Sub())
//同理该行不报错
val t5:Tclass2[Sub] = new Tclass2[Super](new Super())
//不变
//由于 不变 Tclass[Super] 是Tclass[Sub] 没有父子关系 因此 类型不匹配不能相互赋值 所以两行都报错
// val t6:Tclass2[Super] = new Tclass2[Sub](new Sub())
//val t7:Tclass3[Sub] = new Tclass3[Super](new Super())
}
//定义两个有父子关系的类 Super 和 Sub
class Super
class Sub extends Super
//定义协变类
class Tclass[+T](param:T){
}
//定义逆变类
class Tclass2[-T](param:T){
}
//定义不变类
class Tclass3[T](param:T){
}