Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using v. Not Using the `self` Type

Tags:

scala

Given the following traits:

scala> trait Foo { self => 
     |   def f: String = self.getClass.getName
     | }
defined trait Foo

scala> trait Bar { 
     |  def f: String = this.getClass.getName
     | }
defined trait Bar

And then making classes that extend them:

scala> class FooImpl extends Foo {} 
defined class FooImpl

scala> class BarImpl extends Bar {}
defined class BarImpl

And then calling their f methods on new instances:

scala> (new FooImpl).f
res1: String = FooImpl

scala> (new BarImpl).f
res4: String = BarImpl

The REPL shows that they print out the same values - the class's name.

Perhaps this isn't a good example. But what's the difference of using self in the above Foo compared to Bar, which uses this?

like image 424
Kevin Meredith Avatar asked Jul 22 '15 12:07

Kevin Meredith


2 Answers

In your case there's no difference—you're just using another name for this. Self types are useful when you need to disambiguate between different thiss. For example:

abstract class Foo { self =>
  def bar: Int
  def qux = new Foo {
    def bar = self.bar
  }
}

If we wrote def bar = this.bar here, the compiler would complain that our definition of bar is just calling itself recursively, since the this would be referring to the anonymous subclass of Foo we're defining in qux, not the outside Foo.

like image 109
Travis Brown Avatar answered Oct 08 '22 17:10

Travis Brown


There is no difference. self is just an alias for this. The only time it will make a difference is if you try to reference them within an inner class or trait, or object of some kind. e.g.:

trait Foo { self => 
    object InnerFoo {
        def f: String = self.getClass.getName
    }
}

trait Bar { 
    object InnerBar {
        def f: String = this.getClass.getName
    }
}

class FooImpl extends Foo

class BarImpl extends Bar

scala> (new FooImpl).InnerFoo.f // self still references the outer type Foo
res4: String = FooImpl

scala> (new BarImpl).InnerBar.f // this references the inner type InnerBar
res5: String = Bar$InnerBar$
like image 24
Michael Zajac Avatar answered Oct 08 '22 18:10

Michael Zajac