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
?
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 this
s. 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
.
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$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With