为什么包含对类型B的对象的引用的类型A的引用变量不能访问类B的成员函数?

时间:2017-12-21 11:51:44

标签: c# class object inheritance c#-4.0

为什么objA不能访问methodB(),因为它包含对B类对象的引用?

Class A 
{
     public void methodA()
     {
           .........
     }
}

Class B:A
{
     public void methodB()
     {
          ..........
     }
}

现在

A obj1= new B();

这会引发错误:

obj1.methodB();
为什么? obj1 包含对 B 类型对象的引用,但仍然无法访问它的成员函数。

3 个答案:

答案 0 :(得分:2)

您声明了A类型的变量:

A obj1

并且A没有名为methodB的方法。如果您希望变量的类型为B,请将其声明为:

B obj1= new B();

(这当然意味着您不能将A的任何其他实现存储在该变量中,只能B。)

或者,如果您不想更改变量,则需要转换变量:

(obj1 as B).methodB();

(如果obj1包含<{1}}的实施, <{1}},那么这当然会失败。)

基本上,当您声明类型为A的变量时,编译器会将其维护为类型B。在声明之后的任何时候都无法保证变量将包含A的实例。我可以包含实现A任何的实例。

答案 1 :(得分:1)

当你将这两行完美地放在一起时,你会想到#34;当然我可以在那个对象上执行methodB()!它显然是 一个B!&#34;。

但现在考虑一下:

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传递给{{1>},则此方法 会对B执行某些操作。但是,首先需要检查您发送的A是否实际上也是B,然后将<{em} A投射到B 。在结果B上,它可以调用MethodB()

答案 2 :(得分:0)

因为它被称为从基类到派生的限制性视图。如果您使用polymorphism实例化对象,就像执行obj1.methodB();一样,obj1只拥有父类中定义的内容。这是可能的,因为我们知道派生类也必须具有这些定义(字段,属性,方法等)。

这就是为什么你不能调用显式obj1.methodB();但你可以用派生类实现调用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();
}