0

私は次の状況にあり、CLRがどのメソッドを呼び出すかをどのように知っているのか疑問に思いました。

public abstract class Shape
{
    public abstract String PrintName();
}

public sealed class Square : Shape
{
    public override String PrintName() { return "Square"; }
}

public sealed class Circle : Shape
{
    public override String PrintName() { return "Circle"; }
}

次に、各形状をインスタンス化します。

Shape square = new Square();   
Shape circle = new Circle();
List<Shape> shapes = new List<Shape> { square, circle };

foreach (Shape s in shapes)
{
    Console.WriteLine(s.PrintName());   
}

// Output:
// Square
// Circle

では、基本型でメソッドを呼び出しているのに、派生クラスでメソッドを呼び出すことができるのはどうしてですか?私はこれがどのように扱われるか混乱しています。

4

2 に答える 2

2

CLR のタイプ セーフ機能により、Foo のインスタンスを作成するときにそれを Bar として扱うことができないため、実行時にオブジェクトのタイプが常に認識されます。したがって、形状で PrintName() を呼び出すと、それが正方形または円のどちらを扱っているかがわかります。

GetType() は非仮想であるため、オーバーライドできないため、オブジェクトの型を偽装できないことに注意してください。

于 2012-12-11T23:52:54.287 に答える
1

をインスタンス化すると、本当に本当にあるShape square = new Square();という事実は損なわれません。変数は実際には実際のオブジェクトへの参照であることを思い出してください。ここにあるように、参照型 (この場合は) は、同じクラスか、インスタンス化された型 ( ) よりも継承階層の上位にある必要があります。squareSquaresquareShapeSquare

インスタンス化後、コンパイラがを参照するとsquare、それが抽象型であることを最初に認識しShapeます。これが参照の型であるためです。したがって、抽象オブジェクトをインスタンス化できないため、これは Shape のサブタイプでなければなりません。あなたが言っnew Square();たので、コンパイラは正確な型を知っています。繰り返しますが、より基本的な (より基本的な) タイプに割り当てたからといって、オブジェクトの正確なタイプが失われるわけではありません。

を呼び出すsquare.PrintName();と、コンパイラは最初に がsquare抽象型で宣言されていることを確認します。この型Shapeには、メソッドPrintName()もあり、abstract とマークされています。これは、子クラスでまったく同じメソッドを探すようにコンパイラーに指示します。子クラスで見つかった場合はPrintName()、すべて問題ありません。正しい関数が実行されます。そうでない場合は、基本クラス定義の抽象という単語を実装する必要があるため、エラーが発生します。

于 2012-12-11T23:51:14.363 に答える