Kevin Meredith
Kevin Meredith

Reputation: 41909

Using v. Not Using the `self` Type

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?

Upvotes: 5

Views: 105

Answers (3)

mikołak
mikołak

Reputation: 9705

In the quoted case, there's basically none, as the other answers outlined.

Using a self-type mainly gives you an opportunity to further define the type of your trait's extenders, say you provide:

self: Boing =>

Where

trait Boing {
    def x
}

then self.x within Foo will be syntactically valid, whereas this.x will fail to compile.

(Note, however, that you can also refine this the same way, obliviating the need for an explicit self-type identifier)

Upvotes: 2

Michael Zajac
Michael Zajac

Reputation: 55569

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$

Upvotes: 3

Travis Brown
Travis Brown

Reputation: 139038

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.

Upvotes: 5

Related Questions