2

オブジェクト指向プログラミングの世界で「継承」の概念がどのように発生するのか興味があります。私のジレンマを説明させてください(Javaを勉強しているときにこのジレンマに出くわしましたが、私の質問が本質的に一般的であることを願っています):

クラス A とクラス B があるとします。クラス A はクラス Bを「継承」します。これは実際には何を意味するのでしょうか。コンパイラは「新しい」クラスを作成し、クラス A と B の両方の要素を含むオブジェクトにインスタンス化しますか? その場合、アクセス指定子に従ってアクセス制限はどのように実装されますか?

一瞬、次のような流れではないかと思いました。

クラス A のオブジェクトが作成され、次にクラス B のオブジェクトが作成されます。次にJavaは、AのメンバーをBのメンバーに何らかの形で「リンク」し、それらが同じクラスに属しているかのように見せ、アクセス指定子に従ってそれを行います。

しかし、この理論には誤りがあることに気づきました。2 つの異なるクラス B と C がクラス A を継承しているとします。次に、クラス B とクラス C のオブジェクトを作成する場合、それらはクラス A の要素の独自のコピーを持つことになります。したがって、この理論も失敗します。

私は、私の心にある継承についての混乱を説明しようとしていました。頭が痛いです。助けてください。

編集:これは、このサイトで見つけた私の質問に関連するディスカッションへのリンクです。

サブクラスはプライベート フィールドを継承しますか?

4

2 に答える 2

2

私は失敗するかもしれませんが、私はあなたのためにこれについての説明を突き刺すつもりです。

正直なところ、オブジェクトプログラミングの考え方に非常に古典的な間違いを犯しているのではないかと思います。それが、オブジェクトクラスを区別しているのです。事実上すべてのオブジェクト指向言語でのオブジェクト作成は、クラス定義に基づく構築の1つです。あなたの質問から、あなたは一般的にオブジェクト指向言語、特にオブジェクトの継承を集約された個別のオブジェクトとして精神的にモデル化しているように聞こえます。実際には、オブジェクトは集約されたクラス定義の観点から定義されています。

public class A
{
    public A();
}

public class B:A
{
    public B();
}

public class C:B
{
    public C();
}

A-> B-> Cモデルでは、Cの定義は、独自のプロパティに加えて、その直接の祖先であるBのすべてのメンバーに基づいて定義されます。次に、Bは、独自のプロパティに加えて、すべてのメンバーに基づいて定義されます。オブジェクトを作成するプロセスは、依然として一意で個別のイベントであり、オブジェクトは、その多層的な遺産にもかかわらず、インスタンス化時に1つのオブジェクトにすぎません。

特定のメンバーの可視性について:クラスの作成者がクラスを設計および構築するとき、クラスの消費者に公開されるものと、サブクラスに公開または利用可能になるものの2つの異なる視点で利用できるようにするものについて特定の決定を行います。 。プライベートと宣言されたメンバーとフィールドは、サブクラスによるアクセスが「契約上」禁止されている場合でも、すべての子孫クラスの一部です。テレビにはオン/オフボタン、ボリュームコントロール、カラーコントロールの「パブリック」インターフェイスがありますが、内部電子部品や電源などの消費者向けではない「内部」コントロールがあるという大まかな例えをすることができます。供給。それらは、消費者やサブクラスに「表示」または「利用可能」ではありませんが、まだ非常に存在しています。

とはいえ、ほとんどのオブジェクト指向言語には、記述したプロパティ(複数のオブジェクト)を反映し、 Composition(または場合によってはAggregation )と呼ばれるデザインパターンを含む構造があります。これは、クラスが祖先から派生していない場合です。 class-通常、クラスが「sealed」(C#)または「final」(Java)(または継承を禁止するその他の指定)として宣言されているためです。これにより、クラスの使用に関心のある開発者は、クラスを別のクラスのメンバーにする必要があります。クラスのオブジェクトがインスタンス化されると、両方のクラスの個別のオブジェクトがあります。

あなたは以下を持っているかもしれません:

public final class InterestingThing
{
    //definitions
    public InterestingThing()
}

public final class MyThing
{
    InterestingThing _interestingThing = new InterestingThing();

    public MyThing()
}

これは、元の質問で説明した種類のシナリオであり、MyThingの作成は、InterestingThingの明確な作成を意味します。また、この構造は通常、対象となる元のクラスの設計と定義によって強制されることにも注意してください。

最終的に、オブジェクトはクラスによって定義され、多重継承されたクラスは依然として単なるクラスですが、優れたインクリメンタルオブジェクト設計に基づいた、洗練された、できればますます堅牢な階層になっています。

何らかの形で、この説明があなたの質問に答えるのに役立つことを願っています。

于 2012-09-22T19:03:21.460 に答える
1

クラスAはクラスBを「継承」します。これは実際にはどういう意味ですか?

クラスAがクラスBを拡張する場合、クラスAはBのすべてのメンバー(フィールドとメソッド)を継承します。つまり、クラスAは、クラスAの本体で宣言されていなくても、これらのメンバーを持ちます。

クラスAが特定のメンバーへのアクセスを許可されているかどうかは関係ありません。

クラスAのオブジェクトが作成され、次にクラスBのオブジェクトが作成されます。次に、JavaはAのメンバーをBのメンバーに「リンク」し、同じクラスに属しているように見せます。これは、アクセス指定子に従って行われます。

いいえ。クラスAの単一のオブジェクトが作成されます。そのオブジェクトには、たまたますべての継承されたメンバーが含まれています。たとえば、次の場合:

class B {
    private int x;
}

class A extends B {
    private int y;
}

ランタイムは、クラスAのすべてのオブジェクトについて、の値xとの値を格納しますy

クラスAのコードがの値にアクセスしないxことは、Aのソースコードがコンパイル時に名前を使用しないことを確認し、実行時にクラスをロードするときxにAのバイトコードがフィールドを参照しないことを確認することによって強制されます。x言い換えると、アクセス修飾子はメモリレイアウトに依存しません。

于 2012-09-22T19:36:45.567 に答える