5

「//Compiles」の行がコンパイルされる理由と、「//DOS't Compile」の行がコンパイルされない理由を誰か教えてもらえますか?

A が暗黙的に B に変換可能であり、その逆ではない理由がわかりません。

public class SomeClass {

 static public void Test() {
  AClass a = new AClass();
  BClass b = new BClass();

  a = b; // Compiles
  b = a; // Doesn't compile
 }
}

public class AClass {
 public void AMethod() { 
     Console.WriteLine("AMethod");
 }
}

public class BClass : AClass { 
 public void BMethod() {
  Console.WriteLine("BMethod");
 }
}

ありがとう!

4

10 に答える 10

15

B は A が行うすべてのことを行いますが、A は必ずしも B が行うすべてを行うわけではありません。次のように考えてください。

AClass --> Shape
BClass --> Circle

Shape a = new Shape();
Circle b = new Circle();

a = b; // works because a is of type "Shape" and a circle is a specific shape
b = a; // doesn't work because b is of type "Circle" and a could be a square.
于 2009-09-24T00:07:29.367 に答える
8

クラスの名前を AClass から Mammal に、BClass から Dog に変更しましょう。


a = b; // you're putting a dog on a variable of type Mammal. That's OK.
b = a; // You're putting a mammal (could be a cat, a monkey, etc.) on a variable of type Dog.

最良の例ではないかもしれませんが、理解するには十分かもしれません。

于 2009-09-24T00:05:09.693 に答える
4

これは、リスコフの置換原則に直接従います。

q(x)をタイプTのオブジェクトxについて証明可能なプロパティとします。次に、タイプSのオブジェクトyに対してq(y)が真である必要があります。ここで、SはTのサブタイプです。

つまり、基本クラスの代わりに派生クラスを常に使用できます。基本クラスは派生クラスが行うことを実行できないため、通常はその逆は不可能です。

(私はここでタイムラインを混同していることを知っています-継承が最初で、リスコフが2番目に来ました-しかし、彼女は継承がどのように使用されることを意図しているかをうまく説明しました)

于 2009-09-24T00:22:59.343 に答える
4

クラスからインスタンス化されたオブジェクトは、そのスーパークラスの型として扱われる場合がありますが、サブクラスの型として扱うことはできません

  • サブクラスはそのスーパークラスとして扱うことができますが、逆方向には扱うことができません。

より抽象的な言葉で:

public class HarleyExample
{
    static public void Test()
    {
        Motorcycle a = new Motorcycle();
            HarleyDavidson b = new HarleyDavidson();
            Motorcycle c = new Motorcycle(); //Just a plain motorcycle
            a = b; // A Harley can be treated as a regular motorcycle
            //b = a; // Not just any motorcycle is a Harley

            Console.WriteLine("Is A a motorcycle?  " + (a is Motorcycle)); 
            Console.WriteLine("Is A a harley?      " + (a is HarleyDavidson));
            Console.WriteLine();
            Console.WriteLine("Is B a motorcycle?  " + (b is Motorcycle));
            Console.WriteLine("Is B a harley?      " + (b is HarleyDavidson));
            Console.WriteLine();
            Console.WriteLine("Is C a motorcycle?  " + (c is Motorcycle));
            Console.WriteLine("Is C a harley?      " + (c is HarleyDavidson));

            Console.ReadKey();
    }
}

public class Motorcycle
{
    public void Cruise()
    {
        Console.WriteLine("Cruising");
    }
}

public class HarleyDavidson : Motorcycle
{
    public void CruiseInStyle()
    {
        Console.WriteLine("Cruising in style on a Harley");
    }
}
于 2009-09-24T00:09:03.313 に答える
1

他のみんなが言ったことを言い換えるようなものです。これがあなたにとってそれをより明確にするかどうかはわかりません。

'a'は、AMethod()メソッドをサポートするAClass型のオブジェクトとして宣言されています。

'b'は、BMethod()メソッドをサポートするタイプBClassのオブジェクトとして宣言され、AClassのサブクラスであるため、親スーパークラスから継承するため、AMethod()メソッドもサポートします。

したがって、コンパイラはAMethod()のみを呼び出すことを期待しているため、BClass型のオブジェクトをAClass型の変数に簡単に割り当てることができます。

ただし、コンパイラがAMethod()またはBMethod()のいずれかを呼び出す必要があると予想される可能性があるため、AClass型のオブジェクトをBClass型の変数に割り当てることはできません。もちろん、それはできません。 AClassオブジェクトとしての後者はそれをサポートしません。

于 2009-09-24T00:22:02.233 に答える
1

A は暗黙的に B に変換できません。B は A に変換できます。

foo = bar

「bar」を「foo」のタイプに変換しようとします。

(つまり、暗黙の変換に関して「割り当て」がどのように機能するかを誤解しているだけだと思います。)

于 2009-09-24T00:04:53.010 に答える
1

これは C# とはほとんど関係ありません。それは基本的な継承です。a は BClass 型ではありません。BClass に追加のフィールド/プロパティがあるとしたら? でこれらのメンバーの 1 つにアクセスしようとするとどうなりますか?

于 2009-09-24T00:06:23.660 に答える
1

のすべてのインスタンスはBClassAClassBClass が から継承されているためAClassです。AClassより具体的ではないBClassため、暗黙的に B から A に変換できます

于 2009-09-24T00:06:56.750 に答える
1

BClassは のサブクラスAClass(またはAClassのスーパークラスBClass) であり、サブクラスの関係は「である」関係です。したがって、bが のインスタンスである場合、 のBClassインスタンスでもありますAClass。これがb、変数aでポイントするのは問題ないが、 でポイントaするのは問題がある理由bです。追加の仮定が必要になるからです。

于 2009-09-24T00:07:06.453 に答える
1

おそらく、あなたの質問は「スーパークラスからサブクラスへの暗黙的な変換が許可されているのはなぜですか?」.

実際、それは逆です。サブクラスはスーパークラスのインスタンスですが、その逆ではないため、型に互換性がありません。

メソッドまたは定数が 1 つしかない非常に小さなスーパークラスを想像してみてください。ここで、キッチン シンクを含むすべてを定義するサブクラスを想像してみてください。これらはほぼ完全に異なるタイプです。ただし、サブクラスは依然としてスーパークラスのインスタンスです。その1つのメソッドまたは定数があります。

一方、スーパークラスには、継承されたクラスが実装するものはほとんどありません。親が子クラスのインスタンスであるには「ほぼ」で十分ですが、子を期待するメソッドに親クラスを渡すと、利用できるものはほとんどないため、機能しない可能性があります。

于 2009-09-24T00:10:11.897 に答える