110,571
社区成员
发帖
与我相关
我的任务
分享
static void Main(string[] args)
{
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
//父类的引用指向子类的对象
Console.WriteLine("1--a1.show(b)--" + a1.show(b));//A and A
Console.WriteLine("2--a1.show(c)--" + a1.show(c));//A and A
Console.WriteLine("3--a1.show(d)--" + a1.show(d));//A and D
Console.WriteLine("4--a2.show(b)--" + a2.show(b));//B and A
Console.WriteLine("5--a2.show(c)--" + a2.show(c));//B and A
Console.WriteLine("6--a2.show(d)--" + a2.show(d));//A and D
Console.WriteLine("7--b.show(b)--" + b.show(b));// B and B
Console.WriteLine("8--b.show(c)--" + b.show(c));// B and B
Console.WriteLine("9--b.show(d)--" + b.show(d));// B and B
Console.ReadLine();
}
}
class A
{
public string show(D obj)
{
//return ("A and D");
return string.Format("A and D :{0}({1})", this.GetType().Name, obj.GetType().Name);
}
public virtual string show(A obj)
{
//return ("A and A");
return string.Format("A and A :{0}({1})", this.GetType().Name, obj.GetType().Name);
}
}
class B : A
{
public string show(B obj)
{
return string.Format("B and B :{0}({1})", this.GetType().Name, obj.GetType().Name);
}
public override string show(A obj)
{
return string.Format("B and A :{0}({1})*", this.GetType().Name, obj.GetType().Name);
}
}
IL_007c: nop
IL_007d: ldstr "5----"
IL_0082: ldloc.1
IL_0083: ldloc.3
IL_0084: callvirt instance string ConsoleApp1.A::show(class ConsoleApp1.A)
IL_0089: call string [mscorlib]System.String::Concat(string, string)
IL_008e: call void [mscorlib]System.Console::WriteLine(string)
IL_0093: nop
IL_0094: ldstr "6----"
IL_0099: ldloc.1
IL_009a: ldloc.s d
IL_009c: callvirt instance string ConsoleApp1.A::show(class ConsoleApp1.D)
IL_00a1: call string [mscorlib]System.String::Concat(string, string)
IL_00a6: call void [mscorlib]System.Console::WriteLine(string)
IL_00ab: nop
这其实对着你的 c# 代码,是很好的参考。并不需要你会用汇编编程,这里会“猜”就行了。void test(A obj)
{
..........
}
这里过程 test 用来处理某个任务,定义为以兼容A类型的对象为输入参数,那么test方法说明我们实现了某种应用程序使用 obj 的操作流程,但是这个流程其实可以在不改变 test 代码的前提下随时改变运行细节的,这就是靠为 obj 参数传入兼容于A 类型的子类型的对象实例来扩展/修改 test 代码。 public virtual string show(A obj)
{
return ("A and A");
}
这里是体现了重载的技术。
运行时,执行 callvirt 机制,会根据 this 对象的实际类型开始查找 show 实际方法,也就是根据 a2 引用了一个 B 类型对象实例所以从 B 类型开始查找 show 方法,这时候立刻找到了 A 的的第二个 show 方法有一个 B 类型上的重写,子类B类扩展(修改)了A类的特性(通过override)。
在写好和测试好一些针对父类/父接口的代码工程的前提下,子类既继承了父类特性又重写了父类的个别特性,这就是面向对象技术。这需要分析一些应用领域的对象类型/接口之间的继承关系,并且实际操作程序来在针对父类型/接口的代码中使用子类型的对象实例,慢慢实际体会。所以一个比较简单的,你能看的懂的描述是 皇帝说要盖间屋 要金丝楠木,到宰相那里换成黄花梨,到县官那里换成了普通硬木 盖房 x=new 谁呢? 无论他override多少级,主要看你右边new了谁,是让谁做。 皇帝做就是金丝楠木,县官做就是普通硬木
求分析每一个输出的原因。(注释的是输出的结果——一个都看不懂) 这里父类的引用指向子类的对象怎么理解?
[quote=引用 11 楼 xuzuning 的回复:] 为啥要写成B b = new C(); B b 是说 b 是 B 的引用,而 new C() 是 C的实例(B 还是 C 的父类 这就是你说的 父类的引用指向子类的对象