How is Nothing merupakan subtipe dari setiap jenis lainnya di Scala

19

Saya mengambil kursus coursera Martin Odersky tentang pemrograman fungsional dengan scala, dan untuk saat ini saya telah belajar dua hal yang bersama-sama tidak masuk akal:

  1. Scala tidak mendukung banyak pewarisan
  2. Nothing adalah subtipe dari setiap tipe lainnya

Kedua pernyataan ini tidak bisa hidup bersama, jadi bagaimana tepatnya hal ini dilakukan? dan apa sebenarnya arti dari "subtipe dari setiap tipe lain"

Edit 1

Dalam Scala API , Nothingdidefinisikan sebagai abstract final class Nothing extends Any... jadi bagaimana ia dapat memperluas kelas lain?

vainolo
sumber
Halaman ini mungkin sedikit membantu: artima.com/pins1ed/scalas-hierarchy.html
jhewlett
Sejauh yang saya bisa lihat, itu didefinisikan sebagai "sifat akhir Tidak ada yang meluas" scala-lang.org/api/2.7.6/scala/Nothing.html
Den
8
Anda adalah tipe dan kelas yang membingungkan. Kedua hal itu sangat berbeda. Sayangnya, Anda bukan satu-satunya yang bingung dengan perbedaan itu, dan benar - benar sayangnya, beberapa dari mereka yang bingung kebetulan adalah perancang bahasa populer seperti Java, C # dan C ++. Itu tidak mengatakan bahwa itu Nothingadalah subkelas dari setiap kelas lainnya. Ia mengatakan bahwa ini adalah subtipe dari setiap tipe lainnya .
Jörg W Mittag
1
@delnan: Antarmuka Java diambil langsung dari protokol Smalltalk. Di Smalltalk, hanya protokol yang bertipe, kelas tidak. Di Jawa, baik antarmuka dan kelas adalah tipe. Itu salah. Kelas bukan tipe, hanya antarmuka. Fakta bahwa semua bahasa ini memiliki hal-hal yang bertipe dan bukan kelas tidak relevan. Masalahnya adalah bahwa dalam bahasa-bahasa itu kelas adalah tipe, yang salah.
Jörg W Mittag
1
@ JörgWMittag Itu pernyataan yang berbeda, dan sangat bisa diperdebatkan (Saya cenderung setuju bahwa itu berbahaya, tapi saya tidak akan mengaitkan ini dengan kesalahpahaman dalam mengetik). Tidak ada gunanya membahasnya di sini.

Jawaban:

27

Subtyping dan pewarisan adalah dua hal yang berbeda! Nothingtidak memperpanjang segalanya, ini subtipe , hanya meluas Any.

The spesifikasi [§3.5.2] memiliki kasus khusus yang mengatur subtyping-hubungan Nothing:

§3.5.2 Kesesuaian

  • [...]
  • Untuk setiap jenis nilai
    T,scala.Nothing <: T <:scala.Any
  • Untuk setiap konstruktor tipe T(dengan sejumlah parameter tipe apa pun)
    scala.Nothing <: T <: scala.Any
  • [...]

Dimana <:pada dasarnya berarti "adalah subtipe dari".

Adapun cara ini dilakukan: Kami tidak tahu, itu adalah kompiler sihir dan detail implementasi.

Cukup sering bahasa melakukan hal-hal yang Anda sebagai programmer tidak bisa. Sebagai mitra untuk Nothing: Segala sesuatu di Scala mewarisi dari Any, semuanya kecuali Any . Mengapa tidak Anymewarisi sesuatu? Kamu tidak bisa melakukan itu Mengapa Scala bisa melakukan itu? Nah, karena Scala yang menetapkan aturan, bukan Anda. Nothingmenjadi subtipe dari segala sesuatu hanyalah contoh lain dari ini.

hantu0m
sumber
10
BTW: ini persis sama dengan nullditugaskan untuk bidang dari setiap jenis di Jawa. Mengapa itu mungkin? Apakah nullinstance dari setiap kelas? Tidak, ini mungkin karena kompiler mengatakannya. Titik.
Jörg W Mittag
8
Jika saya dapat memperbaiki ini seratus kali, saya akan melakukannya. Jenis dan kelas yang membingungkan adalah salah satu hal terburuk yang dibawa oleh bahasa seperti Java.
Jörg W Mittag
1
Untuk jiwa yang penasaran tentang perbedaan antara pewarisan dan subtipe cmi.ac.in/~madhavan/courses/pl2006/lecturenotes/lecture-notes/... namun saya tidak membelinya - jika Anda mewarisi (seperti extendsdi Jawa, dan tidak sebagai komposisi ) Anda melakukannya untuk subtyping setelah semua.
greenoldman
11

Ketika dia mengatakan bahwa Scala tidak mendukung multiple inheritance, maka dia merujuk pada pewarisan implementasi metode beberapa kali. Tentu saja, Anda dapat mengimplementasikan beberapa antarmuka / sifat dalam sebuah kelas, dan mereka bahkan dapat mendefinisikan metode yang sama, tetapi Anda tidak mendapatkan konflik antara implementasi yang berbeda karena linierisasi sifat.

Secara umum, jika Anda memiliki kelas C1dengan metode f()dan kelas C2juga dengan metode f(), maka multiple inheritance berarti Anda dapat mewarisi kedua implementasi dari f(). Ini dapat menyebabkan berbagai masalah, yang diselesaikan Scala dengan hanya membiarkan Anda mewarisi dari satu kelas dan dalam kasus beberapa sifat dengan memilih satu implementasi berdasarkan urutan sifat tersebut.

Adapun Nothinghal-hal yang sangat sederhana, karena tidak ada yang tidak memiliki atribut atau metode yang ditentukan. Jadi, Anda tidak dapat memiliki konflik warisan. Tetapi saya berasumsi bahwa sebagian besar kejutan Anda berasal dari pemahaman yang berbeda tentang pewarisan berganda.

Setelah Anda memahami bahwa linierisasi sifat secara efektif menghilangkan segala ambiguitas warisan, dan bahwa kami tidak menyebut mewarisi dari banyak sifat sebagai warisan ganda karena itu, maka Anda harus baik-baik saja.

Mengenai bagaimana ini direalisasikan: kompiler pada akhirnya bertanggung jawab untuk ini. Lihat bagian spesifikasi bahasa Scala 3.5.2 kesesuaian, yang antara properti lainnya termasuk:

For every type constructor T (with any number of type parameters), scala.Nothing <: T <: scala.Any.

Atau dengan kata lain, jika Anda ingin mengimplementasikan kompiler dengan benar, ia harus menangani Nothingsebagai subtipe dari segalanya berdasarkan spesifikasi. Untuk alasan yang jelas, Nothingtidak didefinisikan untuk memperluas dari semua kelas yang dimuat ke dalam sistem, tetapi relevansi mendefinisikan Nothingsebagai subtipe terbatas pada semua tempat, di mana subtyping relevan.

Poin penting di sini adalah bahwa tidak ada contoh tipe Nothing, oleh karena itu, perawatannya terbatas hanya untuk pemeriksaan tipe, yang semuanya ada di ranah kompiler.

jujur
sumber
2
Apa yang saya masih tidak mengerti adalah bagaimana hal ini dilakukan ... Lihat hasil edit pertanyaan saya
vainolo
1
"relevansi mendefinisikan Tidak Ada sebagai subtipe terbatas pada semua tempat, di mana subtipe relevan." Apa yang ingin Anda sampaikan dengan itu? X relevan di mana X relevan?
phant0m