0

Answer of this question says "You are not creating an instance of the interface.." I wonder if it is true.

can anyone let me know whose instance is created in below lines of code? and why?

BaseClass b= new Child();

and

 BaseInterface bi= new Child();

Edit : I am asking with respect to C#.net language. If instance is created of child(). why intellisense of visual studio shows Base members while pressing ?

Community
  • 1
  • 1
Ashif Nataliya
  • 912
  • 2
  • 13
  • 28

4 Answers4

4

The actual object created is an instance of the Child class.

The "up-cast" is merely a different view of the same Child object instance.

A statically-typed language limits the operations based on the type of the expression, not the type of the actual object the expressions evaluate to. Because of this, the IntelliSense will only show methods applicable to BaseClass for b and BaseInterface for bi.

This is also why something like Object o = new Child() is valid, even though only the methods defined on Object can be invoked upon o, which is is an expression typed as Object.

The fact that the actual object is a Child can be demonstrated as so:

Child c = new Child();
BaseClass b = c;
BaseInterface bi = c;
c.GetType() == typeof(Child)     // => true
object.ReferenceEquals(c, b)     // => true
object.ReferenceEquals(c, bi)    // => true
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • Do you mean to say child class object is created and then up-casted to Base? if it is so, Can we say final object is of Base? – Ashif Nataliya Sep 12 '14 at 07:43
  • @Akie No. The object is a Child and will always be a Child. The *view* ("the operations that can be performed") is of the base-type (or implemented interface). – user2864740 Sep 12 '14 at 07:44
  • oh ok.. it make sense. One more thing, if it is instance of a child, why I am not allowed to access Child's member using b or bi? – Ashif Nataliya Sep 12 '14 at 07:48
  • @Akie Because the *view* is that of BaseClass/BaseInterface. Imagine if there are two child types, ChildA and ChildB. ChildA defines a method `methodA` and ChildB defined a method `methodB` (what this method does is irrelevant). Since they are both children of BaseClass they can be assigned to `b`. However, since the *type of expression* is used in the static type system then only method defined for BaseClass were allowed. This prevents the case like this: `BaseClass x = new ChildA(); x.methodB();` (Where `methodB` was only defined in ChildB, but not ChildA which is the actual object created). – user2864740 Sep 12 '14 at 07:52
  • Becuse you said yourself you only want to have the view of b or bi onto the child. You can always downcast to Child again as long as it is a child, but the variable type is the one you ahve defined and only those methods are callable. – TomTom Sep 12 '14 at 07:52
  • @user2864740 Okay. it leads me to another question. why it is so difficult for microsoft to allow this call. I mean to say, If we have declared BaseClass x = new ChildA(); why compiler is not able to make it out that x.methodB doesn't belong to b? As it has already compiled the line of declaration code which is BaseClass x = new ChildA();? – Ashif Nataliya Sep 12 '14 at 08:01
  • @Akie Imagine if there is a method, like so: `void m(BaseClass b) { /* .. */ }` and say it is part of a different assembly that is already compiled. And then later it is called as `m(new Random.Next() > 0.5 ? new ClassA() : new ClassB())`. Should `m` be allowed to access `methodA` or `methodB`? (remember these were *only* defined on the respective classes). *Of course not!* This is the exact *same* reason why it cannot be done on the variable `BaseClass b`! This issue is *not* related to a Microsoft whim but is a core "restriction" of static type systems (with separate compilation). – user2864740 Sep 12 '14 at 08:07
  • @Akie That is, the *type of the expression* must first be appropriate. `ClassA a = new ClassA(); a.methodA();` - Okay! `BaseClass x = new ClassA(); ((ClassA)x).methodA();` - Okay! `BaseClass x = new ClassB(); ((ClassA)x).methodA();` - Fail, runtime InvalidCastException as ClassB is not assignable as a ClassA! (But it was still *correctly-typed* code that was incorrectly subverted with use of an invalid cast.) – user2864740 Sep 12 '14 at 08:11
  • @Akie Now, In Real Life, I would use `var x = new ChildA();` (which is equivalent to `ChildA x = new ChildA()`). Then I would use all the available methods/properties defined on ChildA that I needed in the current function and only when I "handed off" the object would it be treated as a BaseClass or BaseInterface expression. (There are a few times when var is not appropriate, but it normally Does What I Want.) – user2864740 Sep 12 '14 at 08:19
  • @user2864740 superb.. Nicely explained. Thanks.. :) – Ashif Nataliya Sep 16 '14 at 10:06
2

This is a very basic question, yet a very, very important one. But I'm not sure this site is the best medium for getting your answer (and more importantly, for understanding it). Try to take a lesson in OOP somewhere, or look for an online presentation detailing it.

Short answer

Runtime type and Static type are two very different things.

Longer answer:

In a statically typed language as C# (or java, or F#, or a bunch of others), a variable always has a static type. The static type is the type that the compiler proved the variable is of, because you told it it is, or because it inferred it (in case of var or lambda arguments for instance).

Some exemples:

int i; //i is of type int
BaseClass b; //b is of class BaseClass
IEnumerable<int> list; //list implements interface IEnumerable<int>
var s = "foo"; //s is inferred to be of type string

This is static typing. It means the variable is of the given type. It does not mean that the object in the variable is this type (which would not even make sense for an interface!), it just means that the compiler has proof that the object inside is assignable to this type (which exactly means it can be put into a variable/field of that type).

Contrast the runtime type. The runtime type is the actual type of the instance. It's only a runtime thing, the compiler cannot access it. It is what is effectively there.

When you statically make method and property calls, you can only call properties and methods from the static type. Simply because it's the only type the compiler can know about. When you're writing

BaseInterface bi= new Child();

You're effectively telling the compiler "I ask you to forget this object is a Child, treat it as a BaseInterface". And that's exactly what the compiler does: you cannot access bi's member that are specific to the Child class.

In fact, this assignation is just a short way to make two very different operations. It's the same as

BaseInterface bi; // I create a "bi" variable. Its static type is BaseInterface
bi = new Child() // Instanciate an object of runtime type Child and assign it to the bi variable

Assigning a value to the variable does not the change its static type.

Falanwe
  • 4,636
  • 22
  • 37
2

BaseClass b= new Child(); - the new Child() calls the constructor of class Child which initializes the object(creates a new instance), the reference type will be Base class. So if BaseClass a has baseClassMet() and class Child() has an aditional method childMet(), you can call the methods defined only in the BaseClass.

and

BaseInterface bi= new Child(); With the interface first of all you cannot instantiate an interface directly. You can assign to an interface a class that implements that interface.

So in this case lets say that Base interface has a method definition void interfMet(); As you know in the class that implements this interface you are obligated to implement this method. The object reference bi being type of BaseInterface will have access only to methods that the interface declares. You cannot accces with bi(interface reference type) methods of Child class. If you really want to access methods of Child you have to do a cast. I hope this helps you.

enter image description here


interface BaseInterface{
    void interMet();
}
class BaseClass{
    void baseClassMet(){
        System.out.println("baseClassMet method in superclass");
    }
}
public class Child extends BaseClass implements BaseInterface{
    //overrided method
    void baseClassMet(){
        System.out.println("baseClass method in extended class");
    }

    //method of child
    void childMet(){
        System.out.println("Child met");
    }
    public void interMet() {
        System.out.println("Implemented method");
    }

    public static void main(String[] args) {
        Child c = new Child();
        c.baseClassMet();// prints "baseClass method in extended class"

        BaseClass b = new Child();
        b.baseClassMet();// prints "baseClass method in extended class"
        b.childMet//can't access object method childMet() like this // Does not compile

        ((Child)b).childMet();//you can do it like this telling the compiler that
        //you are sure that b point to a Child object

        BaseClass b1 = new BaseClass();
        b1.baseClassMet();//prints "baseClassMet method in superclass"

        BaseInterface bi = new Child();//assigning bi of type BaseInterface(interface) the object Child
        bi.interMet(); // this prints "Child met"
    }}
xyclops
  • 88
  • 1
  • 5
0

the declared type of the reference is the perspective you choose to interract with the Child instance , the perspective oopingly speaking is a super class or Interface of the Child.

Genjuro
  • 7,405
  • 7
  • 41
  • 61