2

Why can't objA access methodB() since it contains the reference to an object of class B type?

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

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

now

A obj1= new B();

this throws an error:

obj1.methodB();

why ? obj1 contains the reference to an object of type B but still, it can't access member functions of it.

  • 2
    Let's say `ClassA` was `Fruit` and `ClassB` was `Apple`. `MethodA` is `EatFruit` and `MethodB` is `RemoveAppleCore`. Does it make sense to call `RemoveAppleCore` on **any** fruit (remember, it might be a strawberry or some other fruit)? – mjwills Dec 21 '17 at 11:54
  • 2
    If you assign to a type `A` then the compiler doesn't know that it's a `B`. It could be just an `A` or even a `C`! – DavidG Dec 21 '17 at 11:54
  • https://stackoverflow.com/questions/2662369/covariance-and-contravariance-real-world-example might read that. As a complete answer on a question – Vladimir Dec 21 '17 at 11:55

3 Answers3

2

You declared the variable of type A:

A obj1

And A has no method called methodB. If you want the variable to be of type B, declare it as such:

B obj1= new B();

(This would of course mean that you can't store any other implementations of A in that variable, only B.)

Or if you don't want to change the variable then you'd need to cast the variable:

(obj1 as B).methodB();

(This would of course fail if obj1 ever contains an implementation of A that isn't a B.)

Basically, when you declare the variable of type A, the compiler maintains it as type A. There is no guarantee at any point after declaration that the variable would contain an instance of B. I could contain an instance of anything that implements A.

David
  • 208,112
  • 36
  • 198
  • 279
1

When you put those two lines nicely together, you will think "of course i can execute methodB() on that object! It is a B, obviously!".

But now consider this:

private void DoSomethingWithAnA(A obj1)
{
    obj1.MethodB();
}

Why would this work? In this method, you only know that you receive an object A, nobody will assume that you have to call it with an object B. After all, if your method wanted to do something with a B, it should have asked for a B, not an A!

Of course, I can call the method with a B, this would not be a problem:

DoSomethingWithAnA(new B());

But that doesn't mean that DoSomethingWithAnA all of a sudden will do something with a B, it just does something with an A.

If you also want to do something B-specific, you can, however:

private void DoSomething(A obj1)
{
    obj1.MethodA();
    if (obj1 is B)
    {
        ((B)obj1).MethodB();
    }
}

This method would do something with a B if you pass it a B. However, it first needs to check if the A you send is actually also a B, and then it casts the A to a B. On the resulting B it can then call MethodB().

oerkelens
  • 5,053
  • 1
  • 22
  • 29
0

Because its called restrictive view from base class to derived. If you instantiate object using polymorphism like you do obj1.methodB(); your obj1 posses only things defined in parent class. This is possible because we know that derived class MUST have that definitions too (fields, properties, methods etc).

So that's why you cant call explicit obj1.methodB();but you can call methodA() with derived class implementation.

Examples:

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

Imagine that you have class C,D and so on, if you instantiate them with restrictive view you can call common method (defined in parent class) for all of them (children).

Example

List<A> list = new List() {objB,objC,objD};
foreach(A obj in list){
       obj.MethodA();
}
NSKBpro
  • 373
  • 1
  • 14