Why is implicit conversion allowed from superclass to subclass?

最后都变了- 提交于 2019-12-05 09:54:36

Because B does everything that A does but A does not necessarily do everything that B does. Think of it this way:

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.
Alfred Myers

Let's change the name of the classes from AClass to Mammal and BClass to 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.

Maybe not the best example, but it may be enough for you to understand.

This directly follows from the Liskov Substitution Principle:

Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T

In other words, the derived class can always be used in place of the base class. It's usually not possibel the other way round - because the base class can't do what the derived class does.

(I know I am mixing up the timeline here - inheritance was first, Liskov came second - but she put nicely how inheritance is intended to be used)

An object instantiated from a class may be treated as the type of any of its super-classes, but cannot be treated as the type of a subclass.

  • A subclass can be treated as its superclass, but never in the opposite direction.

In more abstract terms:

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

A is not implicitly convertible to B. B is convertible to A.

In

foo = bar

it's going to try to convert 'bar' to the type of 'foo'.

(That is, I think you are just misinterpreting how 'assignment' works with regards to implicit conversions.)

This has little to do with C#; it's basic inheritance. a is not of type BClass. What if BClass had additional fields/properties? What happens when you attempt to access one of those members on a?

Because all instances of BClass are also AClass since BClass inherits from AClass. AClass is less specific than BClass hence you can implicitly convert from B to A

BClass is a subclass of AClass (or AClass is a superclass of BClass), and the subclass relationship is an "is a" relationship. So if b is an instance of BClass, it is also an instance of AClass. This is why it is fine to point to b with the variable a, but it is not OK to point to a with b, because that requires an additional assumption.

Sort of paraphrasing what everyone else had said. I don't know if this makes it any clearer for you.

'a' is declared as an object of type AClass which supports the AMethod() method.

'b' is declared as an object of type BClass which supports the BMethod() method and, being a subclass of AClass, will also support the AMethod() method as it inherits it from its parent superclass.

So you can easily assign an object of type BClass to a variable of type AClass as the compiler will expect to only ever call AMethod() on it which is fine.

However, you can't assign an object of type AClass to a variable of type BClass as the compiler might expect to have to call either AMethod() or BMethod() on it and, of course, it won't be able to do the latter as an AClass object just won't support it.

Possibly you were confused about which was which, as your question asks "Why is implicit conversion allowed from superclass to subclass?".

Actually, it's the other way around. A subclass is an instance of the superclass, but not the other way around, so that's why the types are not compatible.

Imagine a very small superclass with just a single method or constant. Now imagine a subclass that defines everything including a kitchen sink. These are almost completely different types. However, the subclass is still an instance of the superclass; it does have that one method or constant.

The superclass, on the other hand, has almost nothing that the inherited class implements., "Almost" is good enough for the parent to still be an instance of the child class, but passing the parent class to a method expecting the child would most likely not work, as hardly anything is available.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!