scalaエイリアスと自己タイプ

4659 ワード

この別名
scalaのソースコードを見ると、多くのソースコードの冒頭にself=>という言葉があります.これはthisにselfという別名をつけたことに相当します.
class A { 
    self =>  //this  
    val x=2 
    def foo = self.x + this.x 
}

selfはキーワードではなく、this以外の名前で名前を付けることができます(キーワードを除く).上のコードについては,A内部ではthisで現在のオブジェクトを指すこともselfで表すこともでき,両者は等価である.self=>この書き方は自分のタイプの特殊な方法にすぎない.
自己タイプ(self type)
書式:this:X=>
trait A { 
    this: X =>
}

this:X=>Aがインスタンス化時またはAのサブクラスを定義する際に、指定したXタイプを混入しなければならないことを要求し、このXタイプを現在のタイプとして指定することもできる:class A { this:A => }自己タイプの存在は、現在のクラスを「抽象的」にすることに相当します.これは、自己タイプthis:X=>の存在のため、現在のクラスがインスタンスを構築する際にXタイプを同時に満たす必要があるため、現在のオブジェクト(this)も指定したタイプに合致すると仮定します.
scala> new C //    
:10: error: class C cannot be instantiated because it does not conform to its self-type C with X

// ok,            (C with X)   
scala> val c = new C with X

Cのサブクラスを定義際には、自身のタイプの制約によりXタイプも満たさなければならない、すなわちサブクラスもXに混入しなければならない.
scalaの公式サイトの例を見てみましょう.
trait User {
  def username: String
}

trait Tweeter {
  this: User =>  // reassign this
  def tweet(tweetText: String) = println(s"$username: $tweetText")
}

class VerifiedTweeter(val username_ : String) extends Tweeter with User {  // We mixin User because Tweeter required it
    def username = s"real $username_"
}

val realBeyonce = new VerifiedTweeter("Beyonce")
realBeyonce.tweet("Just spilled my glass of lemonade")  // prints "real Beyonce: Just spilled my glass of lemonade"

VerifiedTweeterクラスは、特質Tweeterを拡張するには、特質Userを同時に使用する必要があります.注意深い学生は以上の例が特質traitの中で発生していることに気づいた.scala公式にも自己タイプは特質traitタイプでなければならないことを強調している.つまりself:T=>中のTtraitでなければならない.trait会報でなければclass needs to be trait to be mixed in.の間違いである.
Self-types are a way to declare that a trait must be mixed into another trait, even though it doesn’t directly extend it. That makes the members of the dependency available without imports. https://docs.scala-lang.org/tour/self-types.html
さらにいくつかの例を見てみましょう.
// Scala Program that uses self type 
trait with_powers 
{  
    var mind ="extra-ordinary";  
      
} 
trait without_powers 
{ 
    var mind="ordinary"; 
} 
trait person 
{  
    def brain(); 
} 
  
// class extend trait 
class extraordinary_person extends person 
{    
    // reassign this 
    this: with_powers => 
    override def brain() = println(s"super hero brain is $mind!"); 
} 
  
// class extend trait 
class ordinary_person extends person 
{    
    // reassign this 
    this: without_powers => 
    override def brain() = println(s"normal human brain is $mind."); 
} 
  
// Creating object 
object GFG 
{ 
    // Main method 
    def main(args:Array[String]) 
    { 
        val hero = new extraordinary_person() with with_powers; 
        val mohan = new ordinary_person() with without_powers; 
          
        //val mohan= new ordinary_person() with with_powers; ERROR 
        //does not conform to ordinary_person's self type 
        hero.brain(); 
        mohan.brain(); 
    } 
} 

// Output:
// super hero brain is extra-ordinary!.
// normal human brain is ordinary.

上記の例では、with_powerswithout_powers、およびpersonといういくつかの特質を作成していますが、extraordinary_personおよびordinary_person2つのクラスはそれぞれpersonを継承しています.また、2つのクラスはそれぞれ自身のタイプを宣言しています.2つのクラスをインスタンス化する際にはmix in自身のタイプのtraitを必要とします.
もう1つの例を見てみましょう.
// Scala Program that uses self type 
trait A 
{  
    def x = 1
} 
  
// trait extend another trait 
trait B extends A 
{ 
    override def x = super.x * 5
} 
  
// trait extend another trait 
trait C1 extends B 
{ 
    override def x = 2
} 
  
// trait extend another trait 
trait C2 extends A 
{  
    this: B=> 
    override def x = 2
      
} 
  
// Creating object 
object GFG 
{ 
    // Main method 
    def main(args:Array[String]) 
    { 
        println((new C1 with B).x); 
        println((new C2 with B).x); 
    } 
} 

traitは直接newできませんが、上(new C1 with B)withでブレンドタイプオブジェクトを構築し、ブレンドタイプオブジェクトのxを呼び出すべきです.(new C2 with B)のうちC 2には自己タイプBがあるため、直接Bの中のxの定義が呼び出され、C 2はAから継承するのでsuper.xは実際には2で、結果は10で、興味のある学生は少しデバッグしてみてください.
参照先:https://www.geeksforgeeks.org/scala-self-types-annotation/https://docs.scala-lang.org/tour/self-types.html http://hongjiang.info/scala-type-system-self-type/http://hongjiang.info/scala-self-type-and-di/https://blog.csdn.net/bluishglc/article/details/60739183