为什么objA不能访问methodB(),因为它包含对B类对象的引用?
Class A
{
public void methodA()
{
.........
}
}
Class B:A
{
public void methodB()
{
..........
}
}
现在
A obj1= new B();
这会抛出一个错误:
obj1.methodB();
为什么? obj1包含对类型B的对象的引用,但仍然无法访问它的成员函数。
你声明了A
类型的变量:
A obj1
并且A
没有称为methodB
的方法。如果您希望变量的类型为B
,请将其声明为:
B obj1= new B();
(这当然意味着你不能将A
的任何其他实现存储在该变量中,只有B
。)
或者,如果您不想更改变量,则需要转换变量:
(obj1 as B).methodB();
(如果obj1
包含A
不是B
的实现,那么这当然会失败。)
基本上,当您声明类型为A
的变量时,编译器会将其保持为A
类型。声明后,在变量将包含B
实例的任何时候都无法保证。我可以包含任何实现A
的实例。
当你把这两条线很好地放在一起时,你会想“当然我可以在那个物体上执行methodB()
!显然它是一个B
!”。
但现在考虑一下:
private void DoSomethingWithAnA(A obj1)
{
obj1.MethodB();
}
为什么会这样?在这种方法中,你只知道你收到一个对象A
,没有人会认为你必须用对象B
来调用它。毕竟,如果你的方法想用B
做一些事情,它应该要求B
,而不是A
!
当然,我可以使用B
调用该方法,这不会是一个问题:
DoSomethingWithAnA(new B());
但这并不意味着DoSomethingWithAnA
突然会用B
做点什么,它只是用A
做点什么。
如果您还想要做一些特定于B的事情,您可以:
private void DoSomething(A obj1)
{
obj1.MethodA();
if (obj1 is B)
{
((B)obj1).MethodB();
}
}
如果你传递B
,这个方法会对B
做一些事情。但是,它首先需要检查你发送的A
是否实际上也是一个B
,然后它将A
投射到B
。在得到的B
上,它可以调用MethodB()
。
因为它被称为从基类到派生的限制性视图。如果使用polymorphism
实例化对象,就像你执行obj1.methodB();
一样,你的obj1
只拥有在父类中定义的东西。这是可能的,因为我们知道派生类也必须具有这些定义(字段,属性,方法等)。
这就是为什么你不能调用显式的obj1.methodB();
but,你可以用派生类实现调用methodA()
。
例子:
A objA = new A();
objA.methodA(); //calling method implementation of class A
objA.methodB(); //compile time error -> class A doesn't have that method
A objA = new B();
objA.methodA(); //calling method implementation of class B
objA.methodB(); //compile time error -> during restrictive view trough parent class
B objB = new B();
objB.methodA(); //calling method implementation of class B
objB.methodB(); //calling method implementation of class B
想象一下,你有C,D等类,如果用限制性视图实例化它们,你可以为所有这些(子)调用公共方法(在父类中定义)。
例
List<A> list = new List() {objB,objC,objD};
foreach(A obj in list){
obj.MethodA();
}