2009-09-24 7 views
5

"//コンパイル"の行がコンパイルされ、なぜ "//コンパイルできません"という行がなぜなぜ表示されないのですか?スーパークラスからサブクラスへの暗黙の変換が許可されるのはなぜですか?

私はなぜ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"); 
} 
} 

ありがとうございます! foo 'での型に「バー」を変換しようとするだろう

foo = bar 

ではA.

に変換可能である

答えて

1

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

(それは私があなただけの「割り当て」は暗黙の変換に関してどのように機能するかを誤解していると思う、である。)

8

のは、犬に哺乳類とBClassにAClassはからのクラスの名前を変更してみましょう。


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. 

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

+7

動物園への旅行なしでOOPについて話すことはできません。 =) – JohnFx

+0

ちょうどカモノハシは言及していません! –

+0

Nitpick: "哺乳類"。 – McPherrinM

1

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

1

BClassのすべてのインスタンスもAClassです.BClassはAClassから継承されているためです。 AClassAClassのサブクラス(またはAClassBClassのスーパークラスである)され、したがって、あなたが暗黙

1

BClassにBから変換することができBClass未満特異的であり、サブクラス関係は、関係「ある」です。したがって、bBClassのインスタンスである場合、それはAClassのインスタンスにもなります。このため、変数aを使用してbを指しても問題ありませんが、abを指すのはOKではありません。追加の前提が必要なためです。

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. 
+1

+1すてきな説明 –

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"); 
    } 
} 
+0

私はこれをデバッグすると、a = bが実行されると、デバッガの "HarelyDavidson"型として表示されることを理解できないようです。これがどういうことができるのか分かりません... –

+1

簡単。デバッガは.GetType()を呼び出します。 オートバイのGetType()がオートバイを返します。 HarleyDavidsonのGetType()はHarleyDavidsonを返します。 宣言された型ではなく、有効な型を取得します。 –

+0

@HC私の更新を見て、物事を明確にするのに役立つことを願っています。 –

1

は、おそらくあなたはどの程度混乱していたあなたの質問をを尋ねると、された「なぜ、暗黙の型変換は、スーパークラスからサブクラスに許可されています?」

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

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

一方、スーパークラスは、継承されたクラスが実装するものはほとんどありません。 "Almost"は、親クラスが子クラスのインスタンスになり、親クラスをメソッド子供はほとんど何も利用できないため、ほとんど働かない可能性があります。

1

言い換えれば誰もが言いました。これがあなたのためにもっと明確になるかどうかはわかりません。

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

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

コンパイラがAMethod()を呼び出すことだけが期待されるので、BClass型のオブジェクトをAClass型の変数に簡単に割り当てることができます。

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

4

これは直接Liskov Substitution Principleから次の

Q(x)はその後、Q(y)はタイプSここで、Sのオブジェクトのyについて真でなければならない型TのオブジェクトXについて証明可能性としますTのサブタイプT

つまり、派生クラスは常にベースクラスの代わりに使用できます。基本クラスは、派生クラスが何をすることができないので、通常、他の方法では可能ではありません。

(私はここでタイムラインを混合しています知っている - 継承が最初だった、リスコフ第二に来た - しかし、彼女は継承が使用されることを意図している方法をうまく入れ)

+2

+1私は科学で私を盲目にしています –

+0

hehe :)あなたのサービスで! – peterchen

関連する問題