重载方法——引用和实例化对象的区别

Overloaded methods - references and instantiated objects difference

在上面的代码片段中,我有一个基础 class 形状和两个派生的 classes RectangleTriangle。我实例化了它们,但是对于一个 Triangle 对象,我使用了他的基础 class.
的引用类型 所以现在当我调用方法 calculate() 时,它会更喜欢调用采用基本 class 参数的方法。

这样做的目的是什么?

我正在创建 Triangle 对象而不是 Shape 对象我只是使用基 class 的引用。我的另一个问题是,它们与使用基 class 的引用和从派生而不是使用派生引用实例化对象有什么其他区别吗?

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

实现多态性的正确方法是将您的计算函数放在每个 classes(包括您的基础 class)中,而不是静态的。然后你会从实例中调用函数,你会得到你预期的结果:

Shape shape = new Triangle(tc, 4, 4, 4);
shape.calculate(); <<-- this will output "triangle"

1ST 问题:所以现在当我调用一个方法 calculate() 时,它更愿意调用采用基本 class 参数的方法。这样做的目的是什么?

答:怎么可能是别的呢?编译器无法确定对象的 "actual" 类型,因为只有在 运行 时才能真正知道。您有责任使用 "reflection"(例如 GetType() 和 typeof() )将该父对象(形状)转换为其子对象(三角形),然后将其作为参数传递。如果它以任何其他方式工作,您将无法正确实施下面的方法。

 public foo(object var1){
     // Test for var1's type and perform a operation
 }

第二个问题:它们与使用基引用 class 和从派生而不是使用派生引用实例化对象有任何其他区别吗?

答案:在内存中没有,引用总是指向相同的数据但是上下文会改变。这意味着对象是哪种类型的对象(子对象或父对象)决定了可以访问哪个fields/methods。将对象转换为哪种类型不会改变实际存储在堆上的内容,而是会改变您可以访问的内容。下面的代码片段对此进行了演示。

    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
    }