OOP言語およびタイプのクラス


9

プログラミング言語理論では、型は値のセットです。たとえば、「int」型はすべての整数値のセットです。

OOP言語では、クラスはタイプですよね?

クラスが複数のメンバーで定義されている場合、例えば

class myclass{
    int a; 
    double b;
}

クラスについて話すとき、

  • (a,b)どこaint型で、b二重である」、または
  • 「{ (x,y)| xは任意のint、y任意のdoubleです}」?

のインスタンスはmyclassどういう意味ですか?

  • (a,b)どこaint型で、b二重である」、または
  • メモリ空間を占有し、(必ずしもそうである必要はない、つまり空である可能性があります)を格納できるオブジェクト(x,y)。ここxで、int yはあり、doubleはありますか?

2
クラスはタイプです。"{(x、y)| x is any int、y is any double}" "は、2つのことを除いて、ほぼ正しいでしょう:1)クラスが概念的にレコードである間にタプルを使用した-参照する名前ではなく、位置によってフィールド;および2)未フィールドを持つすべてのレコードabキリアンはフォース言及としてMyClassのは、その型のメンバーである。同型のフィールドを持つレコードへabタイプのintdouble-あなたはそのような記録を取り、にそれを回すことができますインスタンスmyclass
Doval

1
強く型付けされた言語では、クラスは型です。弱く型付けされた言語では、型である場合とそうでない場合があります。
shawnhcorey 2015年

1
プログラミング言語理論では、型は値のセットですか?他の本や他の先生、あるいはその両方を手に入れる必要があると思います。「変数」または「定数」には「タイプ」があり、多くの場合「値」があります。ゼロ値タイプ、スカラー、および複合値タイプがあり、変数または定数の値にサブ変数/サブ定数が含まれています。
user1703394 2015年

1
@ user1703394タイプ値のセットです。32ビット整数型は、2 ^ 32の異なる値のセットです。式がその型の値に評価される場合、その値がそのセットに含まれていることがわかります。数学演算子は、そのセットの値に対する関数です。
ドバル、2015年

1
また、タイプを値のセットとして考えることにも注意が必要です。セットには、タイプに厳密に適用できない関係があります。型を概念化する場合、これは優れたモデルですが、物事をより詳細に検討し始めると故障します。さらに、サブタイピングを導入するとさらに故障します。
Telastyn、2015年

回答:


30

どちらでもない。

同じフィールドタイプのセットが同じクラスであると分類するのに十分なのか、それとも同じように名前を付ける必要があるのか​​、とあなたは聞いていると思います。答えは次のとおりです。「でも、同じ種類持っていない同じ名前が十分です!」構造的に同等のクラスは、必ずしもタイプ互換ではありません。

たとえば、CartesianCoordinatesPolarCordinatesクラスがある場合、両方にフィー​​ルドとして2つの数値があり、Numberタイプと名前が同じであっても、互換性PolarCoordinatesはなく、のインスタンスはのインスタンスCartesianCoordinates。彼らの意図によって別の種類に能力の目的ではなく、現在の実装では、より安全、より保守コードを書くのに非常に有用な部分です。


9
いくつかの言語が構造的に同等であることにことに留意すべきである、一方が他方(多くの場合、その逆)のサブタイプを入力作るのに十分な。それは明らかに珍しい/不人気です。
Telastyn、2015年

7
@Tim typedefは型を作成せず、既存の型を参照するために使用される名前に別名を付けます。
ドバル、2015年

1
@DevSolar彼はCについて明示的に言及しており、C ++以外には、そのキーワードを使用する他の言語については知りません。
ドヴァル2015年

3
@Telastyn-それらの言語は火で殺されるべきです。
Jon Story

4
@JonStory構造サブタイプはモジュールレベルで役立ちます。それが欠けているため、interfaceユニットテストを実行する場合は、すべてをJavaおよびC#に変換する必要があります。実行時にクラスを変更する意図がなくても、プログラムが使用する特定のクラスを変更できるように、大量のボイラープレートを作成することになります。
ドバル、2015年

6

タイプはセットではありません。

ご覧のとおり、集合論には単純に型には適用さない多数の機能があり、その逆も同様です。たとえば、オブジェクトには単一の正規型があります。複数の異なるタイプのインスタンスである可能性がありますが、インスタンス化に使用されたのはこれらのタイプの1つだけです。集合論には「標準的な」集合の概念はありません。

セット理論では、サブセットに属するものを記述するルールがある場合は、オンザフライサブセット作成できます。型理論は一般にこれを許可しません。ほとんどの言語にはNumberタイプまたは類似のタイプがありますが、EvenNumberタイプがなく、タイプを作成するのも簡単ではありません。つまり、型自体を定義するのは簡単ですが、Numberたまたま存在する既存のは、魔法のようにに変換されることはありませんEvenNumber

実際、セットはまったく別の種類の動物であるため、サブセットを「作成」できると言うのは多少不誠実です。集合論では、それらのサブセットは、それらを定義できるすべての無限の方法ですでに存在しています。型理論では、通常、有限数(大きい場合)の型を常に扱うことを期待しています。存在すると言われている唯一の型は、実際に定義したものであり、定義できるすべての型ではありません。

セットは、直接的または間接的に自分自身を含むことできません。Pythonなどの一部の言語では、型の規則性が低くなっています(Pythonでは、typeの標準型はtypeでありobject、のインスタンスと見なされますobject)。一方、ほとんどの言語では、ユーザー定義型がこの種のトリックに従事することを許可していません。

セットは通常、互いに含まれることなくオーバーラップできます。これは型理論では一般的ではありませんが、一部の言語では多重継承の形でサポートされています。Javaなどの他の言語では、これの制限された形式のみを許可するか、完全に禁止します。

空の型が存在します(これは下部型と呼ばれます)が、ほとんどの言語ではそれをサポートしていないか、ファーストクラスの型とは見なしていません。「他のすべてのタイプを含むタイプ」も存在し(トップタイプと呼ばれます)、セット理論とは異なり、広くサポートされています。

注意:一部のコメンターが以前に指摘したように(スレッドがチャットに移動する前に)、集合論やその他の標準的な数学構造で型をモデル化することが可能です。たとえば、タイプをセットとしてモデル化するのではなく、タイプメンバーシップをリレーションとしてモデル化できます。しかし、実際には、集合論ではなくカテゴリー理論を使用すると、これははるかに簡単になります。これは、たとえばHaskellがその型理論をモデル化する方法です。


「サブタイピング」の概念は、「サブセット」の概念とはまったく異なります。Xがのサブタイプである場合は、のインスタンスをのインスタンスに置き換えるYことができ、プログラムはある意味で引き続き「機能」します。これは構造的というよりは振る舞いですが、一部の言語(たとえば、Go、Rust、おそらくC)は、プログラマーまたは言語実装のいずれかのために、後者を選択しています。YX


コメントは詳細な議論のためのものではありません。この会話はチャットに移動しました
ワールドエンジニア

4

代数的データ型はこれを議論する方法です。

タイプを組み合わせるには、3つの基本的な方法があります。

  • 製品。それは基本的にあなたが考えていることです:

    struct IntXDouble{
      int a; 
      double b;
    }
    

    製品タイプです。その値は、one intとoneのすべての可能な組み合わせ(つまり、タプル)ですdouble。数値タイプをセットとして考える場合、製品タイプのカーディナリティーは、実際にはフィールドのカーディナリティーの積です。

  • 和。手続き型言語では、これを直接表現するのは少し厄介です(通常、タグ付きunionを使用して行われます)。

    data IntOrDouble = AnInt Int
                     | ADouble Double
    

    このタイプの値は、いずれかのフォームを持っているAnInt 345、またはADouble 4.23、しかし(各値は、2つの数値を持っている製品の種類、用とは異なり)関与する唯一つの番号が常にあります。したがって、カーディナリティ:最初にすべてのInt値を列挙し、それぞれをAnIntコンストラクターと組み合わせる必要があります。さらに、すべてのDouble値、それぞれをと組み合わせたものADouble。したがって、合計タイプ

  • べき乗1。オブジェクト指向の明確な対応がまったくないため、ここでは詳しく説明しません。

クラスはどうですか?キーワードstructではなく、意図的に使用しclassましたIntXDouble。実は、型としてのクラスは、そのフィールドによって実際には特徴付けられておらず、それらは単なる実装の詳細です。重要な要素は、むしろ、クラスが区別できる値を持つことができることです。

あるものの、クラスの値は、することができ、関連の値がいずれかのそれのサブクラスの!クラスは和タイプではなく、製品の種類、実際にあるように、次の場合ABの両方から派生されるだろうがmyClassmyClass本質的の合計になりますAB。実際の実装に関係なく。


1 これは関数です(数学的な意味で!)。関数型Int -> Doubleは指数関数で表されDoubleIntます。あなたの言語が適切な機能を持っていないと悪いことに...


2
申し訳ありませんが、これは非常に悪い答えだと思います。関数に明確なオブジェクト指向のアナログ、つまりメソッド(および単一メソッドのインターフェースタイプ)があります。オブジェクトの基本的な定義は、オブジェクトが状態(フィールド/データメンバー)と動作(メソッド/メンバー関数)の両方を持つことです。あなたの答えは後者を無視します。
ruakh 2015年

@ruakh:いいえ。もちろんオブジェクト指向で関数を実装することもできますが、一般にメソッドは関数ではありません(状態を変更するためなど)。さらに言えば、手続き型言語の「関数」もまた、関数です。確かに、単一静的メソッドのインターフェースは関数/指数型に最も近くなりますが、この質問には関係がないので、それについての説明は避けたいと思いました。
左回り、2015年

...さらに重要なのは、私の足首行動を考慮することです。実際、通常、振る舞いが継承を使用する理由であり、さまざまな可能な振る舞いの統合により、OOクラスの合計タイプの側面が正確にキャプチャされます。
左回り、2015年

@ruakhメソッドはそのオブジェクトなしではあり得ません。最も近いアナログはstaticメソッドですが、それらはまだ一流の値ではありません。ほとんどのオブジェクト指向言語の特徴は、オブジェクトを最小の構成要素として受け取ることです。そのため、もっと小さなものが必要場合は、オブジェクトでそれを偽造する必要があります。たとえば、関数が等しいかどうかを比較しても意味がありませんが、2つの偽関数オブジェクトを比較することはできます。
ドバル、2015年

@Doval 1)AFAIKの周りにメソッドを渡すことができるので、それらは一流の値です。2)JSの人々は平等のために関数を比較することは理にかなっています。
Den

2

申し訳ありませんが、「生の」理論については知りません。私は実際的なアプローチしか提供できません。これがprogrammers.SEで受け入れられることを願っています。私はここでのエチケットに慣れていません。


OOPの中心的なテーマは情報の隠蔽です。クラスのデータメンバーが正確に何であるかは、クライアントには関係ありません。クライアントは、インスタンスに(メソッド/メンバー関数を呼び出す)メッセージを送信します。これにより、内部状態が変更される場合と変更されない場合があります。クラスの内部は、クライアントが影響を受けることなく変更される可能性があるという考えです。

これに対する反論は、クラスがその内部表現が「有効」のままであることを保証する責任があるということです。(簡略化された)電話番号を2つの整数に格納するクラスを想定します。

    int areacode;
    int number;

これらはクラスのデータメンバーです。しかし、このクラスは、おそらくになりますはるかにちょうどそのデータメンバーよりも、それは確かに「int型のx int型のすべての可能な値の集合」として定義可能ではありません。データメンバーに直接アクセスするべきではありません。

インスタンスを構築すると、負の数が拒否される場合があります。おそらく、この構造は何らかの方法でエリアコードを正規化するか、整数全体を検証することもできます。あなたは、このようにずっと近いあなたに終わるでしょう"(a,b) where a is an int and b is a double"、それは確かではないので、任意のそのクラスに格納された2つのint型。

しかし、クラスに関する限り、それは本当に重要ではありません。クラス定義するのはデータメンバーの型でも、それらの可能な値の範囲でもありません。クラスに対して定義されるのはメソッドです。

これらのメソッドが同じである限り、実装者はデータ型を浮動小数点、BIGNUM、文字列などに変更できますが、すべての実用的な目的では、同じクラスになります。


クライアントが気付くことなく内部表現のそのような変更を確実に行うことができるようにする設計パターンがあります(たとえば、不透明なポインターの背後にデータメンバーを隠すC ++のpimplイディオム)。


1
It is neither the type of the data members, nor the range of their possible values that defines the class, it's the methods that are defined for it.データメンバーは、非表示にする場合にのみクラスを定義しません。これは最も一般的なケースかもしれませんが、すべてのクラスに当てはまるとは限りません。単一のフィールドでさえパブリックである場合、それはそのメソッドと同じくらい重要です。
ドバル、2015年

1
Javaでコーディングしている場合を除き、問題を選択する余地がなく、おかしな動作のない偽のレコードもclassesである必要があります。(それらfinalをマークすることは、ポイントを理解するのに役立ちますが、それでも)。protectedただし、メンバーにはまだ問題があります。これは継承され、サブクラスのインプリメンターの2番目のAPIの一部を形成する可能性があります。
Doval 2015年

1
@Doval:私はこれが「理論」の質問であることを理解しました。そのため、私は実際の言語の問題をできるだけ避けました。(私がJavaにprotectedできるだけ
近づか

3
問題は、a classが言語依存の構造であることです。私の知る限りclass、型理論のようなものはありません。
Doval

1
@Doval:型理論自体はクラスに適用されないという意味ではありませんか?
DevSolar 2015年

2
  • タイプは、値、化合物の構造、またはあなたが持っているのカテゴリー/範囲の説明です。OOPwise、それは「インターフェース」に似ています。(言語に依存しない意味では言語固有感覚、それほど。でJavaは、例えば、intあるタイプが、とは関係がありませんinterface同様に、パブリック/プロテクテッドフィールド仕様の一部ではありませんinterface、しかしである「インターフェース」又は一部のタイプ。)

    要点は、具体的な定義よりも意味的な定義です。公開されたフィールド/動作とその定義された目的が一致する限り、要素のみを構造化します。両方がない場合、型の互換性はありません。

  • クラスは、タイプの実現です。これは、内部構造、添付された動作などを実際に定義するテンプレートです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.