プログラミング言語理論では、型は値のセットです。例えば。タイプ「int」は、すべての整数値のセットです。
OOP言語では、クラスはタイプですよね?
クラスが複数のメンバーで定義されている場合。
class myclass{
int a;
double b;
}
クラスについて話すとき、
(a,b)
where a
is int and b
is a double"、または(x,y)
| x
は任意の整数、y
は任意の倍数」} "?myclass
のインスタンスはどういう意味ですか?
(a,b)
where a
is int and b
is a double"、または(x,y)
を格納できる(必ずしも空である必要はない)オブジェクト。ここで、x
は任意のintであり、y
は任意のdoubleどちらでもない。
同じフィールドタイプのセットが同じクラスであると分類するのに十分なのか、それとも同じように名前を付ける必要があるのか、とあなたは聞いていると思います。答えは、「同じタイプでなくてもand同じ名前で十分です!」 構造的に同等のクラスは必ずしもタイプ互換ではありません。
たとえば、CartesianCoordinates
クラスとPolarCordinates
クラスがある場合、両方にフィールドとして2つの数値があり、同じNumber
タイプと同じ名前、ただしそれらはまだ互換性がなく、PolarCoordinates
のインスタンスはCartesianCoordinates
のインスタンスではありません。現在の実装ではなく、意図された目的によって型を分離する機能は、より安全で保守可能なコードを書くのに非常に便利な部分です。
タイプはセットではありません。
ご覧のとおり、集合論には単純にタイプに適用しない機能、および逆の機能がいくつかあります。たとえば、オブジェクトには単一の正規型があります。いくつかの異なるタイプのインスタンスである可能性がありますが、インスタンス化に使用されたのはこれらのタイプの1つだけです。集合論には「標準的な」集合の概念はありません。
セット理論では、サブセットに属するものを記述するルールがある場合、 オンザフライでサブセットを作成 できます。型理論は一般にこれを許可しません。ほとんどの言語にはNumber
タイプまたはそれに類似したタイプがありますが、それらはEvenNumber
タイプを持たないので、作成するのも簡単ではありません。つまり、型自体を定義するのは簡単ですが、偶然に存在する既存のNumber
sは、魔法のようにEvenNumber
sに変換されません。
実際、セットはまったく別の種類の動物であるため、サブセットを「作成」できると言うのは多少不誠実です。集合論では、それらのサブセットはすでに存在しています。型理論では、通常、有限数(大きい場合)の型を常に処理することを期待しています。存在すると言われる唯一のタイプは、実際に定義したタイプであり、定義できるすべてのタイプではありません。
セットは 直接または間接的に自分自身を含めることはできません です。 Pythonなどの一部の言語では、型の規則性が低くなります(Pythonでは、type
の正規型はtype
であり、object
はobject
のインスタンスと見なされます)。一方、ほとんどの言語では、user-defined型がこの種のトリックに従事することを許可していません。
セットは通常、互いに含まれることなくオーバーラップできます。これは型理論では一般的ではありませんが、一部の言語は多重継承の形でサポートしています。 Javaなどの他の言語では、これの制限された形式のみを許可するか、完全に禁止します。
空のタイプは存在します(これは ボトムタイプ と呼ばれます)が、ほとんどの言語ではサポートされていないか、ファーストクラスタイプとは見なされません。 「他のすべてのタイプを含むタイプ」も存在し(これは top type と呼ばれます)、集合論とは異なり、広くサポートされています。
[〜#〜] nb [〜#〜]:一部のコメント投稿者が以前に(スレッドがチャットに移動される前に)指摘したように、集合論やその他の標準的な数学構造を持つモデルタイプ。たとえば、タイプとしてセットをモデル化するのではなく、タイプメンバーシップをリレーションとしてモデル化できます。しかし実際には、セット理論の代わりに カテゴリ理論 を使用すると、これははるかに簡単になります。これは、たとえばHaskellがその型理論をモデル化する方法です。
「サブタイピング」の概念は、「サブセット」の概念とはまったく異なります。 X
がY
のサブタイプである場合、これは substituteY
のインスタンスをX
のインスタンスに置き換えても、プログラムが何らかの意味で「機能する」ことを意味します。これは構造的というよりは振る舞いですが、一部の言語(たとえば、Go、Rust、おそらくC)は、プログラマーまたは言語実装のいずれかのために、後者を選択しています。
代数的データ型 はこれを議論する方法です。
タイプを組み合わせるには、3つの基本的な方法があります。
製品。それは基本的にあなたが考えていることです:
struct IntXDouble{
int a;
double b;
}
製品タイプです。その値は、1つのint
と1つのdouble
の可能なすべての組み合わせ(つまり、タプル)です。数値タイプをセットとして考える場合、製品タイプのカーディナリティーは実際にはフィールドのカーディナリティーの積です。
和。手続き型言語では、これを直接表現するのは少し厄介です(通常、タグ付き共用体で行われます)。理解を深めるために、Haskellの合計型を次に示します。
data IntOrDouble = AnInt Int
| ADouble Double
このタイプの値の形式はAnInt 345
、またはADouble 4.23
ですが、関係する数値は常に1つだけです(各値に2つの数値がある製品タイプとは異なります)。したがって、カーディナリティ:最初にすべてのInt
値を列挙し、それぞれをAnInt
コンストラクターと組み合わせる必要があります。 Plus、すべてのDouble
値、それぞれADouble
と組み合わせます。したがって、合計タイプです。
べき乗1。明確なOO対応がないため、ここでは詳しく説明しません。
クラスはどうですか? struct
には、class
ではなく、意図的にキーワードIntXDouble
を使用しました。実は、型としてのクラスは、そのフィールドによって実際には特徴付けられておらず、それらは単なる実装の詳細です。重要な要素は、クラスが持つことができる区別可能な値です。
は何に関連するかでも、クラスの値はanyのサブクラスです!したがって、クラスは実際には積タイプではなく合計タイプです。A
とB
の両方がmyClass
から派生する場合、myClass
は基本的にA
とB
の合計。実際の実装に関係なく。
1これは関数です 数学的な意味で! );関数タイプInt -> Double
は指数関数Double
で表されますInt
。あなたの言語が適切な機能を持っていないと悪いことに...
申し訳ありませんが、「生の」理論については知りません。私は実際的なアプローチしか提供できません。これがprogrammers.SEで受け入れられることを願っています。ここのエチケットはよく知りません。
OOP isinformation hidingの中心的なテーマは、クラスのデータメンバーが何であるか、正確には、クライアントには関係ないはずです。クライアントは、messagesをインスタンスに(メソッドの呼び出し/メンバー関数を)送信します。これは、内部状態を変更する場合と変更しない場合があります。クラスの内部は、影響を受けるクライアント。
これに対する補足として、classは、その内部表現が「有効」のままであることを保証する責任があります。 (簡略化された)電話番号を2つの整数に格納するクラスを想定します。
_ int areacode;
int number;
_
これらは、クラスのデータメンバーです。ただし、クラスはおそらくそのデータメンバーよりもはるかに多くなり、「int x intのすべての可能な値のセット」として定義することはできません。データメンバーに直接アクセスするべきではありません。
インスタンスを作成すると、負の数が拒否される場合があります。おそらく、この構造は何らかの方法でエリアコードを正規化するか、整数全体を検証することもできます。したがって、そのクラスに格納されているanyの2つのintは確かにないため、"(a,b) where a is an int and b is a double"
にかなり近くなります。
しかし、クラスに関する限り、それは本当に重要ではありません。 クラスを定義するのは、データメンバーのタイプでも、可能な値の範囲でもないクラスを定義する、それはそれに定義されているメソッド
これらのメソッドが同じである限り、実装者はデータ型を浮動小数点、BIGNUM、文字列などに変更でき、すべての実用的な目的のために同じクラスのままです。
クライアントが気付くことなく内部表現のそのような変更を確実に行うことができるようにする設計パターンがあります(たとえば、データメンバーを 不透明なポインター の後ろに隠すC++のpimplイディオム)。
typeは、カテゴリ/値の範囲、複合構造、または何を持っているかの説明です。 OOPwise、それは「インターフェース」に似ています。 (言語に依存しない意味で。言語固有の意味ではありません。たとえば、Javaでは、int
はtypeですが、interface
。パブリック/保護フィールド仕様もinterface
の一部ではありませんが、are「インターフェース」の一部またはtypeです。 )
要点は、具体的な定義よりも意味的な定義です。公開されたフィールド/動作およびそれらの定義された目的が整列しているため、要素のみを構造化します。両方がない場合、型の互換性はありません。
classは型の実現です。これは、実際に内部構造、アタッチされた動作などを定義するテンプレートです。