Scalaの他のすべてのタイプのサブタイプは何でもない


19

私は、Martin Oderskyのscalaを使った関数型プログラミングのコースを受講していますが、今のところ、意味が合わない2つのことを学びました。

  1. Scalaは多重継承をサポートしていません
  2. Nothing 他のすべてのタイプのサブタイプです

これら2つのステートメントは共存できませんが、これはどのように行われますか?そして、「他のすべてのタイプのサブタイプ」の意味は正確に何ですか

編集1

ではScalaのAPINothingとして定義されているabstract final class Nothing extends Any...ので、どのようにそれは他のクラスを拡張することができますか?


このページは少し役立つかもしれません:artima.com/pins1ed/scalas-hierarchy.html
jhewlett

私の知る限りでは、それが「最終形質何がどれはみ出していない」と定義されて見ることができるように scala-lang.org/api/2.7.6/scala/Nothing.htmlを
デン

8
型とクラスを混同しています。これら2つは非常に異なるものです。残念ながら、その区別に混乱しているのはあなただけではありません。本当に残念なことに、混乱している人の中には、Java、C#、C ++などの一般的な言語のデザイナーがいる人もいます。それがNothing他のすべてのクラスのサブクラスであるとは言いません。それは他のすべてのタイプのサブタイプであると言います。
ヨルグWミットタグ

1
@delnan:Javaのインターフェースは、Smalltalkのプロトコルから直接取得されます。Smalltalkでは、プロトコルのみが型であり、クラスはそうではありません。Javaではインターフェースクラスの両方がタイプです。それは間違っている。クラスはタイプではなく、インターフェースのみです。これらのすべての言語には、クラスではなく型の物があるという事実は無関係です。問題は、これらの言語ではクラスが型であるということです。これは間違っています。
ヨルグWミットタグ

1
@JörgWMittagこれは別のステートメントであり、非常に議論の余地があります(これは有害であることに同意する傾向がありますが、これはタイピングの誤解に起因するものではありません)。ここで議論する意味はありません。

回答:


27

サブタイピングと継承は2つの異なるものです!すべてを拡張するのでNothingはなく、サブタイプであり、拡張するだけです。Any

仕様[§3.5.2は]のサブタイプ関係を管理する特殊なケースがありますNothing

§3.5.2適合

  • [...]
  • すべての値タイプについて
    Tscala.Nothing <: T <:scala.Any
  • すべての型コンストラクターT(任意の数の型パラメーターを使用)
    scala.Nothing <: T <: scala.Any
  • [...]

どこに<:基本的に「のサブタイプである」という意味。

これがどのように行われるかについてはわかりません。コンパイラの魔法と実装の詳細です。

多くの場合、言語はプログラマーとしてはできないことを行います。対応などNothingからScalaの継承でのすべて:Anyすべてのもの、を除きます Any。なぜAny何かを継承しないのですか?それはできません。なぜScalaはそれができるのですか?まあ、Scalaはあなたではなくルールを設定しているからです。Nothingすべてのサブタイプであることは、この他のインスタンスです。


10
ところで:これはnull、Javaのすべてのタイプのフィールドに割り当て可能であることとまったく同じです。なぜそれが可能ですか?あるnullすべてのクラスのインスタンスは?いいえ、コンパイラーがそう言うので、それは可能です。期間。
ヨルグWミットタグ

8
私がこれを100回賛成できれば、私はそうするでしょう。クラスの混乱は、Javaのような言語がもたらした最悪の事態の1つです。
ヨルグWミットタグ

1
継承とサブタイプの違いについての好奇心cm盛な人向けcmi.ac.in/~madhavan/courses/pl2006/lecturenotes/lecture-notes/…しかし、私はそれを購入しません-継承する場合(extendsJavaのように、作曲としてではなく) )あなたは結局サブタイプ化のためにそれをします。
greenoldman

11

Scalaが多重継承をサポートしていないと彼が言うとき、彼はメソッド実装を複数回継承することを指します。もちろん、クラスに複数のインターフェース/特性を実装でき、同じメソッドを定義することもできますが、特性の線形化により異なる実装間で競合が発生することはありません。

一般に、C1メソッドf()を持つクラスとメソッドを持つクラスC2がある場合f()、多重継承は、の両方の実装を何らかの方法で継承できることを意味しますf()。これによりさまざまな問題が発生する可能性があります。Scalaは、単一のクラスからのみ継承できるようにすることで解決し、複数の特性の場合は、特性の順序に基づいて1つの実装を選択します。

Nothing何も定義された属性やメソッドを持っていないので、物事、本当に簡単です。したがって、継承の競合はありません。しかし、あなたの驚きのほとんどは、多重継承の異なる理解から来ていると思います。

特性の線形化が継承のあいまいさを事実上排除し、それにより複数の特性からの継承を複数の継承として参照しないことを理解したら、問題ありません。

これがどのように実現されるかについては、コンパイラが最終的にこれに責任を負います。Scala言語仕様セクション3.5.2準拠を参照してください。他のプロパティの中には、次のものが含まれます。

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

言い換えれば、コンパイラを正しく実装したい場合はNothing、仕様ごとにすべてのサブタイプとして処理する必要があります。明らかな理由により、Nothingシステムにロードされるすべてのクラスから拡張するように定義されていませんが、Nothingサブタイプとして定義することの関連性は、サブタイプが関連するすべての場所に限定されます。

ここで重要な点は、typeのインスタンスが存在しないことですNothing。したがって、その処理は、すべてコンパイラの領域内にある型チェックに厳密に制限されます。


2
私はまだこれがどのように行われているのか理解していない...私の質問の編集を参照してください
-vainolo

1
「サブタイプとしてNothingを定義することの関連性は、サブタイプが関連するすべての場所に限定されます。」それで何を伝えたいですか?Xが関連する場合、Xは関連しますか?
phant0m
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.