重载方法——引用和实例化对象的区别
Overloaded methods - references and instantiated objects difference
在上面的代码片段中,我有一个基础 class 形状和两个派生的 classes Rectangle
和 Triangle
。我实例化了它们,但是对于一个 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
}
在上面的代码片段中,我有一个基础 class 形状和两个派生的 classes Rectangle
和 Triangle
。我实例化了它们,但是对于一个 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
}