在上面的代码段中,我具有基类形状,并从中有两个派生的类Rectangle
和Triangle
。我实例化它们,但对于一个Triangle
对象,我使用他的基类的参考类型。
因此,现在当我调用方法calculate()
时,它将更喜欢调用正在使用基类参数的方法。
这是什么目的?
我正在创建Triangle
对象而不是Shape
对象,我只使用基类的引用。我的另一个问题是,它们是否与使用基类的参考并从派生中实例化对象而不是使用派生引用有任何其他区别?
public static void Main(string[] args)
{
Point tc = new Point(3, 4);
Point rc = new Point(7, 5);
Shape shape = new Triangle(tc, 4, 4, 4);
calculate(shape);
}
public static void calculate(Shape shape) <<-- new Triangle() with base class ref will came here.
{
Console.WriteLine("shape");
}
public static void calculate(Rectangle rectangle)
{
Console.WriteLine("rectangle");
}
public static void calculate(Triangle triangle) <<-- new Triangle() using triangle ref will came here.
{
Console.WriteLine("triangle");
}
第一个问题:现在,当我调用方法计算((时,它更喜欢调用正在使用基类参数的方法。这是什么目的?
答案:如何其他方式?编译器无法确定对象的"实际"类型,因为只能在运行时才真正知道。使用"反射"(例如getType((和typeof(((将父对象(shape(施加到其子女(三角形(,然后将其作为参数传递,这将是您的责任。如果其他任何方法都可以使用,您将无法正确实现以下方法。
public foo(object var1){
// Test for var1's type and perform a operation
}
第二个问题:它们是否与使用基类的参考并从派生中实例化对象而不是使用派生引用?
是否有其他区别?答案:在内存NO中,引用始终指向相同的数据,但是上下文将会更改。这意味着该对象的哪种类型的对象(子或父(确定可以访问哪些字段/方法。哪种类型的对象被铸造为不会更改实际存储在堆上的东西,而是会更改您可以访问的内容。从下面的代码片段中证明了这一点。
public class Parent {
public int var1 = 1;
}
public class Child : Parent {
public int var2 = 2;
}
public void foo () {
Parent theObject = new Child();
int num1 = theObject.var1; // Valid
int num2 = theObject.var2; // Invalid
int num3 = ((Child)theObject).var2; // Valid
}
实现多态性的正确方法是将计算功能放在每个类(包括基类(中,而不是静态的。然后,您将从实例中调用该功能,然后获得预期的结果:
Shape shape = new Triangle(tc, 4, 4, 4);
shape.calculate(); <<-- this will output "triangle"