What is the syntax meaning of “`class declaration head` { val_name : Type => `class body` }”

后端 未结 3 400
遥遥无期
遥遥无期 2021-01-18 05:11

When reading some articles about Scala, I found some examples with a curious syntax, which I might understand incorrectly

class Child[C <: Child[C]]         


        
相关标签:
3条回答
  • 2021-01-18 05:26

    It is a self type annotation.

    This means that class Child must be of type C, i.e., creates inheritance dependencies which must satisfied for a given class.

    A small example:

    scala> trait Baz
    defined trait Baz
    
    
    scala> class Foo {
         | self:Baz => 
         | }
    defined class Foo
    
    
    scala> val a = new Foo
    <console>:9: error: class Foo cannot be instantiated because it does not conform to its self-type Foo with Baz
           val a = new Foo
                   ^
    
    scala> val a = new Foo with Baz
    a: Foo with Baz = $anon$1@199de181
    
    
    scala> class Bar extends Foo with Baz
    defined class Bar
    

    In this case Foo is required to also be a Baz. Satisfying that requirement, a Foo instance can be created. Also, defining a new class (in this case Bar) there is also the requirement of it being Baz as well.

    See: http://www.scala-lang.org/node/124

    0 讨论(0)
  • 2021-01-18 05:41

    One very useful application of self types is a less verbose implementation of the CRTP ( http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ), e.g.

    abstract class Base[Sub] {
      self:Sub =>
      def add(s:Sub) : Sub
    }
    
    case class Vec3(x:Double,y:Double,z:Double) extends Base[Vec3] {
      def add(that:Vec3) = Vec3(this.x+that.x, this.y+that.y, this.z+that.z)
    }
    

    Attempts to "cheat" with the inheritance won't work:

    class Foo extends Base[Vec3] {
      add(v:Vec3) = v
    }
    
    //error: illegal inheritance;
    //self-type Foo does not conform to Base[Vec3]'s selftype Base[Vec3] with Vec3
    //      class Foo extends Base[Vec3] {
    
    0 讨论(0)
  • 2021-01-18 05:41

    In addition to the inheritance requirement in JaimeJorge's response, self types can be used to give the outer instance a name if you want to refer to it from an inner class:

    scala> class Company(name: String) {
         |   company =>
         |   class Department(name: String) {
         |     override def toString = "Department "+ name +" of "+ company.name
         |   }
         | }
    defined class Company
    
    scala> val c = new Company("ACME")
    c: Company = Company@56a57bb2
    
    scala> val d = new c.Department("Marketing")
    d: c.Department = Department Marketing of ACME
    
    0 讨论(0)
提交回复
热议问题