0

コードのこれら2つの部分の主な違いは何か、なぜ、またはいつ基本クラスへの参照を使用する必要があるのか​​ を誰かが説明できますか?私にとっては同じことです。

internal class MyBaseClass
{
    public string Field = "Hello";
    public void Print()
    {

        Console.WriteLine("This is the base class.");
    }
}

internal class MyDerivedClass : MyBaseClass
{
    public string FieldDerived = "Coucou";
    public new void Print()
    {

        Console.WriteLine("This is the derived class.");
    }
    public new void Print2()
    {

        Console.WriteLine("This is the derived class.");
    }
}

internal class Program
{
    private static void Main()
    {
        MyDerivedClass derived = new MyDerivedClass();
        MyBaseClass mybc = (MyBaseClass) derived;
                            // ↑
                            //   Cast to  base clas
    }
}

そして、これは私にとってまったく同じことをするコードです:

internal class MyBaseClass
{
    public string Field = "Hello";
    public void Print()
    {

        Console.WriteLine("This is the base class.");
    }
}

internal class MyDerivedClass : MyBaseClass
{
    public string FieldDerived = "Coucou";
    public new void Print()
    {

        Console.WriteLine("This is the derived class.");
    }
    public new void Print2()
    {

        Console.WriteLine("This is the derived class.");
    }
}

internal class Program
{
    private static void Main()
    {
        MyDerivedClass derived = new MyDerivedClass();
        MyBaseClass mybc = new MyBaseClass();
                               // ↑
                               //   Use the base class 
    }
}
4

8 に答える 8

2

派生クラスは、is-a 関係を実装するためのものです。クラスを想像してください:

internal class MySpottedDogClass : MyDogClass : MyAnimalClass

斑点のある犬は犬であり、犬は動物だからです。

新しい斑点のある犬を作成する場合

MySpottedDogClass rover = new MySpottedDogClass();

その後、私は呼び出すことができます

rover.countSpots() 

斑点のある犬にのみ適用されるアクション。メソッドは SpottedDog クラスの一部です

rover.bark()

これはすべての犬に適用されるため、犬のクラスで実装されています。

rover.weight()

これはすべての動物に適用されるため、animal クラスに実装されています。サブクラスは、一般的なもののより詳細なバージョンを作成する方法です。オブジェクト指向設計について少し読む必要があると思います

これらの用語で設計を考えると役立つかもしれません。

あなたの最初の例は次のようなものです

SpottedDogClass rover = new SpottedDogClass();
DogClass dogReferenceToRover = (DogClass) rover;

どちらも同じオブジェクトを参照しています。dogReferenceToRover.bark() は問題ありません。dogReferenceToRover.countSpots() は有効ではありません。これは、犬 (斑点のある犬のみ) に対しては実行できず、参照にはオブジェクトではなく型があるためです。

あなたの2番目の例はこのようなものです

SpottedDogClass rover = new SpottedDogClass();
DogClass fido = new DogClass();

今回は斑点犬と犬を作りました。2 つのオブジェクトがあります。

于 2013-04-29T13:53:34.653 に答える
1

わざとらしい例を考えてみると、

abstract class Cake
{
    public virtual bool Edible { get { return true; } }
}

class PooCake : Cake
{
    public new bool Edible { get { return false; } }
}

class TurdCake : Cake
{
    public override bool Edible { get { return false; } }
}

および次のスニペット

var turd = new TurdCake();
var poo = new PooCake();
Console.WriteLine(
    "PooCake is{0} edible",
    poo.Edible ? string.Empty : " not");
Console.WriteLine(
    "PooCake is{0} edible",
    (Cake)poo.Edible ? string.Empty : " not");
Console.WriteLine(
    "TurdCake is{0} edible",
    turd.Edible ? string.Empty : " not");
Console.WriteLine(
    "TurdCake is{0} edible",
    (Cake)turd.Edible ? string.Empty : " not");
Console.ReadKey();

new継承モデルに違反するため、キーワードを非常に慎重に使用する必要があることに気付くでしょう。この場合、ベースのうんちケーキを食べたままになる可能性があります.

コードをデバッグしてステップ実行するとTurdCake、プロパティが正しくオーバーライドされ、基本実装にアクセスできないことがわかります。このPooCake例では、プロパティはシャドウ化されているだけで、基本型への参照によって基本実装が公開されます。これにより、満足のいく結果が得られない可能性があります。

于 2013-04-29T14:21:35.377 に答える
1

最初の例のキャストは冗長です。派生クラスを基底クラスであるかのように扱うことは常に正当だからです。

Print メソッドをオーバーライドする場合 (このシナリオではおそらくこれが必要です) virtual、基本クラスとoverride派生クラスの両方でマークします。次に、基本クラスと派生クラスの間で異なる動作が得られます。

于 2013-04-29T13:46:09.567 に答える
0

おそらく、あなたの質問は、C# のクラスのポリモーフィックな動作に関するものである必要がありましたか?

于 2013-04-29T13:57:40.800 に答える
0

派生クラスは、さまざまな理由で、基本クラスで定義されたメソッドまたはプロパティを非表示にすることがあります。

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

public class BaseClass
{
    public string GetSomeValue() { return "base class"; }
}

派生クラスでは、これは新しいメソッドによって「再配線」できます。

public class DerivedClass : BaseClass
{
    // hides the base method (basically you're hijacking the signature)
    public new string GetSomeValue() { return "derived class"; }
}

new基本クラスではほとんどすべての署名が可能であることに注意してください。これは署名をハイジャックする非常に強力な方法であり、注意して使用する必要があります。

多態的に、 のインスタンスはが呼び出される DerivedClassと常に戻ります。"derived class"GetSomeValue

ただし、派生クラスのメソッドではなく、基本クラスのメソッドを呼び出すことが非常に重要な場合があります。その場合、次のように派生インスタンスをアップキャストするのが理にかなっています。

var result = ((BaseClass)derivedInstance).GetSomeValue();  // returns "base class"

アップキャスト ( (BaseClass)derivedInstance) すると、派生クラスが独自のメソッドを無視し、new代わりに基本クラスのメソッドを呼び出すことができます。これは特定の状況では理にかなっている可能性がありますが、コンポーネントの設計やその他のポリモーフィックに重いコードの持ち上げを行っていない限り、これを日常的に目にすることはないと思います。少なくとも、はそうではありません (目を覆う)。

于 2013-04-29T14:46:52.487 に答える