Pertanyaan Menggunakan v. Tidak Menggunakan Jenis `self`


Mengingat ciri-ciri berikut:

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

Dan kemudian membuat kelas yang memperpanjangnya:

scala> class FooImpl extends Foo {} 
defined class FooImpl

scala> class BarImpl extends Bar {}
defined class BarImpl

Dan kemudian memanggil mereka f metode pada instance baru:

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

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

REPL menunjukkan bahwa mereka mencetak nilai yang sama - nama kelas.

Mungkin ini bukan contoh yang bagus. Tapi apa bedanya menggunakan self di atas Foo dibandingkan dengan Bar, yang menggunakan this?


5
2017-07-22 12:56


asal


Jawaban:


Dalam kasus Anda tidak ada perbedaan — Anda hanya menggunakan nama lain untuk this. Tipe diri berguna ketika Anda perlu membedakan antara yang berbeda thiss. Sebagai contoh:

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

Jika kami menulis def bar = this.bar di sini, kompilator akan mengeluh bahwa definisi kita tentang bar hanya menyebut dirinya secara rekursif, karena this akan mengacu pada subkelas anonim dari Foo kami mendefinisikan qux, bukan di luar Foo.


5
2017-07-22 13:02



Tidak ada perbedaan. self hanya alias untuk this. Satu-satunya waktu yang akan membuat perbedaan adalah jika Anda mencoba mereferensikannya dalam kelas atau sifat batin, atau objek sejenis. misalnya.:

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$

3
2017-07-22 13:02



Dalam kasus yang dikutip, pada dasarnya tidak ada, seperti jawaban yang diuraikan lainnya.

Menggunakan tipe mandiri terutama memberi Anda kesempatan untuk lebih menentukan jenis perluasan ekstensi Anda, katakanlah Anda memberikan:

self: Boing =>

Dimana

trait Boing {
    def x
}

kemudian self.x dalam Foo akan secara sintaksis berlaku, sedangkan this.x akan gagal dikompilasi.

(Perhatikan, bagaimanapun, bahwa Anda juga dapat memperbaiki this dengan cara yang sama, mengabaikan kebutuhan untuk identifier tipe diri eksplisit)


2
2017-07-22 13:09