为什么允许从超类到子类的隐式转换?
有人可以告诉我为什么“//编译”的行编译,以及“//不编译”的行为什么不编译?
我不明白为什么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"); } }
谢谢!
因为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.
让我们将类的名称从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.
也许不是最好的例子,但它可能足以让你理解。
这直接来自Liskov替代原则 :
设q(x)是关于类型T的对象x可certificate的属性。对于类型S的对象y,q(y)应该为真,其中S是T的子类型
换句话说,派生类总是可以用来代替基类。 反过来通常不可能 – 因为基类不能完成派生类所做的事情。
(我知道我在这里混淆了时间表 – inheritance是第一次,Liskov排在第二位 – 但她很好地说明了如何使用inheritance)
从类实例化的对象可以被视为其任何超类的类型 ,但不能被视为子类的类型 。
用更抽象的术语:
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不可隐式转换为B. B可转换为A.
在
foo = bar
它会尝试将’bar’转换为’foo’的类型。
(也就是说,我认为你只是误解了’赋值’在隐式转换方面是如何工作的。)
这与C#几乎没有关系; 这是基本的inheritance。 a不是BClass类型。 如果BClass有其他字段/属性怎么办? 当您尝试访问其中一个成员时会发生什么?
因为BClass
所有实例都是AClass
因为BClassinheritance自AClass
。 AClass
比BClass
更不具体,因此您可以隐式地将B从B转换为A.
BClass
是BClass
的子类(或者AClass
是AClass
的超类),子类关系是“是一种”关系。 因此,如果b
是BClass
的实例,它也是AClass
一个实例。 这就是为什么用变量a
指向b
是好的,但是用b
指向a
是不行的,因为这需要额外的假设。
解释其他人所说的话。 我不知道这是否会让你更清楚。
‘a’被声明为AClass类型的对象,它支持AMethod()方法。
‘b’被声明为BClass类型的对象,它支持BMethod()方法,并且作为AClass的子类,它也将支持AMethod()方法,因为它从它的父超类inheritance它。
因此,您可以轻松地将类型为BClass的对象分配给类型为AClass的变量,因为编译器只希望在其上调用AMethod(),这很好。
但是,您不能将类型为AClass的对象分配给BClass类型的变量,因为编译器可能希望在其上调用AMethod()或BMethod(),当然,它将无法执行后者作为AClass对象只是不支持它。
可能你很困惑哪个是哪个,因为你的问题是“为什么允许从超类到子类的隐式转换?” 。
实际上,这是相反的方式。 子类是超类的一个实例,但不是相反,所以这就是类型不兼容的原因。
想象一下只有一个方法或常量的非常小的超类。 现在想象一个定义所有东西的子类,包括厨房水槽。 这几乎是完全不同的类型。 但是,子类仍然是超类的一个实例; 它确实有一个方法或常数。
另一方面,超类几乎没有inheritance类实现的任何东西。“Almost”足以让父级仍然是子类的实例,但将父类传递给期望子级的方法最多可能不起作用,因为几乎没有任何东西可用。
上述就是C#学习教程:为什么允许从超类到子类的隐式转换?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/956526.html