5

この問題は私を悩ませてきました、そして私は今4つのラッパーを書きました。私はそれを間違っていると確信しており、私の理解がどこに分岐しているのかを理解する必要があります。

金属の棒を表すためにRectangleクラスを使用しているとしましょう。(これは動物よりもうまく機能します)

つまり、基本クラスは「バー」と呼ばれます。

private class Bar
{
   internal Rectangle Area;
}

それで。ここで、300ユニット×10ユニットの長方形を作成します。

private Bar CreateBar()
{
    Bar1 = new Bar1();
    Bar1.Area = new Rectangle(new Point(0,0), new Size(300,10));
    return Bar1;
}

素晴らしいので、ベースバーがあります。

ここで、このバーに材料(たとえば鋼)を持たせたいとしましょう。それで。。。

private class SteelBar : Bar
{
    string Material;
}

だから私がこれをした場合。。。

private SteelBar CreateSteelBar()
{
    SteelBar SteelB = new SteelB();
    Bar B = CreateBar();
    SteelB = B;
    SteelB.Material = "Steel";
    return SteelB;
}

CreateSteelBarを呼び出すと、これから得られるものから、CreateBarを呼び出す鋼棒が作成されます。そのため、300 x 10の長方形の棒鋼と、材料用のヌルまたは空の文字列ができあがります。次に、材料を鋼に設定しました。

私のプログラムで似たようなことをしようとすると、下位のクラスから上位のクラスを暗黙的に作成することはできないと言われ続けます。私が見た動物の例からのすべての継承を考慮すると、これが継承が存在する理由であると私は考えたでしょうが、誰かが私を片付けることができることを望んでいます。

また、私は電話をかけることができると確信していますSteelBar = CreateBar();が、私はここで長い道のりをしました。

4

8 に答える 8

16

CreateBarメソッド ( ) を使用する代わりに、コンストラクターを使用します。

public Bar()
{
    this.Area = new Rectangle(new Point(0,0), new Size(300,10));
}

次に、SteelBar で基本クラスのコンストラクターを呼び出します。

public SteelBar()
{
    this.Material = "Steel";
}

基本クラスのコンストラクターが最初に発生するため、領域は既にセットアップされています。ただし、これについて明示して、コードで表示することはできます。

public SteelBar()
    : base()
{
    this.Material = "Steel";
}

ただし、これは通常、引数を取る特定のコンストラクターが必要な場合にのみ使用されます。

詳細については、C# プログラミング ガイドの「コンストラクター」を参照してください。

于 2012-06-13T17:13:22.477 に答える
3

問題は次のとおりです。

Bar B = CreateBar();
SteelB = B;

Bあらゆる種類のバーです。に割り当てようとしていSteelBarます。それは間違っています。どんな種類の棒でもかまいません (銅、木、ティキなど)。あなたはこれを行うことができます:

SteelBar sb = new SteelBar();
Bar b = sb;

aSteelBarはある種のバーですが、その逆は当てはまりません。

また、 SteelBar = CreateBar() を呼び出すことができると確信しています

あなたは何かが間違っていると確信しています。それを試してみてください; ではなく、任意の種類CreateBarのバーのインスタンスを返します。SteelBar

于 2012-06-13T17:15:34.177 に答える
1

pycruft が述べたように、ベースタイプのオブジェクトをサブタイプ変数に割り当てることはできません。プロパティもSteelBar持っているので、とにかく追加する理由がわかりません。Materialこれは私には冗長に見えます。

やろうとしていることを達成するには、SteelBar最初から を構築する新しいファクトリ メソッドを作成する必要があります。とにかくとしてそれを返すかもしれませBarん。これはFactory Patternの実装になります。

ただし、達成しようとしていることについての詳細情報が役立つ場合があります。

于 2012-06-13T17:16:23.880 に答える
1

下位のクラスから上位のクラスを暗黙的に作成することはできないと言い続けます

私がこれに使用する最良の例はFruitandappleです。継承は「is-a」関係です。appleであるがFruit、である可能性があるため、でFruit はない...appleorangebanana

あなたの例に戻ると、 aSteelBarは a ですBarが、 aBarはaSteelBarである可能性があり WoodenBar、スーパークラスを子クラスにキャストできない理由を説明しています

于 2012-06-13T17:17:20.723 に答える
0

あなたはこれを行うことはできません:

SteelBar = B;

Bar 型の新しいオブジェクトを作成し、それを SteelBar 型の参照に割り当てようとしています。

于 2012-06-13T17:13:13.890 に答える
0

あなたの問題は、あなたがアップキャストしようとしていることだと確信しています:

Bar B = CreateBar();
SteelBar = B;

これは正しくありません。なぜなら、SteelBar はBar(継承されているため) 型である必要がありますが、逆方向に同じことを行うことはできないからです。

反対は合法です:

SteelBar B = CreateBar();
Bar = (Bar)B;

SteelBarの参照をinに格納しようとしているだけですがBar、 などの別のバー タイプである可能性がありますWoodenBar

于 2012-06-13T17:14:45.237 に答える
0

次の例を検討してください。

public class Super {
}

public class Sub : Super {
}

オブジェクト Super を作成した場合、それは「サブ」ではないため、サブとして割り当てることはできません。OO プログラミングでは、派生クラスが少ないという観点からオブジェクトを「扱う」ことができますが、この単純な事実は依然として残っています。

サブではなくスーパーを作成しました。

Super から Sub を作成する唯一の方法は、新しい Sub を作成してプロパティ値をコピーすることです。AutoMapper のようなツールは、これを迅速に行うのにうまく機能します。そうしないと、ありふれた脆弱なコードの行がまとまってしまうことになります。

于 2012-06-13T17:20:59.120 に答える
0

確かに、これはインターフェイスなどの抽象化で実現する方が簡単です...たとえば、IMeasureableとIPhysicalであり、基本クラスではありません...

簡単に表示できるように GUI 表現でのみ BaseClass を使用し、基本クラスに必要なインターフェイスを実装させます。

必要に応じて、封印され、IMeasurable または IPhysical を取る DisplayObject を使用することもできます...

于 2012-06-13T17:16:42.787 に答える