4

I tried the below code in my c# program. This is just for learning the OOPs Concepts.

 class a
    {      
        public void testa()
        {
        }
    }
    class b:a
    {     
        public void testb()
        {
        }
    }

  a a1 = new b();

  b b1 = new a();

I have the following queries regarding the code mentioned above.

  1. Why Im getting error in 2nd line?
  2. what is meant by a a1=new b();
  3. why a1.testb() is not accessible even though constructor of b is assigned to a1?
  4. what is the difference between a a1=new a() and a a1=new b()?
Ardalan Shahgholi
  • 11,967
  • 21
  • 108
  • 144
Tom Cruise
  • 1,395
  • 11
  • 30
  • 58
  • May this link will help you. http://msdn.microsoft.com/en-us/library/vstudio/dd460654.aspx – Karthik AMR Nov 05 '13 at 07:55
  • You need to understand the concepts of inheritance. class b is actually a more well defined and detailed form of class a. So, it has all the features that class a has to offer, but more. That is the reason you can refer b's constructor from a. Now you need to understand that a1.testb() is that extra functionality that class b offers, which class a doesn't possess. So, a1 cannot call testb(). – Wasiq Ali Nov 05 '13 at 08:01
  • @WasiqAli i will agree with you if i wrote a 1=new a() instead of a a1=new b(). in that case i cant access the methods of b. But here since i assigned b's constructor to a why its not accessible? – Tom Cruise Nov 05 '13 at 09:30

6 Answers6

4

1) if you mean this line:

b b = new a();

it is because every b is a but not every a is b

2-3) what is meant by a a1=new b(); why a1.testb() is not accessible even though constructor of b is assigned to a1?

it means that you create object of b class but get reference to it as a(you can treat it trough this reference without casting only as a even it is b)

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • Can you explain what do you mean by "you can treat it trough this reference without casting only as a even it is b"? – Tom Cruise Nov 05 '13 at 09:49
  • 1
    for compiler `a1` is only `a` and it can give you access only to fields/properties/methods defined in `a` class, but you know that in fact it is `b` and you can write something like this(it's called [casting](http://msdn.microsoft.com/en-us/library/ms173105(v=vs.110).aspx)): `b a2 = (b) a1` and compiler will be able to call for all methods of `b` through `a2`. Casting is performed in runtime so if `a1` was not `b` it would give you an runtime error. – Guru Stron Nov 05 '13 at 10:07
  • [C# is for the most part a statically typed language, because the compiler determines facts about the types of every expression. C# is for the most part a type safe language because it prevents values of one static type from being stored in variables of an incompatible type (and other similar type errors).](http://blogs.msdn.com/b/ericlippert/archive/2012/10/15/is-c-a-strongly-typed-or-a-weakly-typed-language.aspx) – Guru Stron Nov 05 '13 at 10:13
4

I change your class and method names to real world equivalents to better understanding. I name a as Animal, testa as Eat, b as Human, and testb as Talk. So we have:

class Animal {      
    public void Eat() { }
}

class Human : Animal {     
    public void Talk() { }
}

Animal a1 = new Human();

Human b1 = new Animal();

OK, return to your questions.

1) You get error on second line, because every animal is NOT a human. Is it?

2) a1=new b() according to our new naming conventions, turns to a1 = new Human which means Animal a1 = new Human. So, that's correct, because human is a kind of animal.

3) a1.testb() according to our new naming conventions, turns to a1.Talk(). Well, a1 is an animal (Animal a1), and we can not expect an animal to talk.

MORE:

Think a class is a group of attributes and behaviors. For example, we have a group named Animal that defines an Eat behavior. And another group named Human that extends Animal group and also it has its own behavior named Talk. As we know, Human has its super-group behaviors too -e.g. Eat in this example-.

When we have an instance of group Animal, we can expect it to eat. But we can not ask it to talk. It's not possible. In the other hand, every item that we choose from group Human, is actually an Animal. So we can ask him to eat.

When we have a Human instance, we can ask him to behave as a Human and as an Animal too. I mean, we can ask him to Talk and we can ask him to Eat too. Every Human can be located in human group, and in animal group.

1) When we say Human b1 = new Animal(); it says exactly: pick up an item from Animal group - right part - and put it in Human group - left part - which is not possible. Because there are a lot of animals which are not human.

2) When we say Animal a1 = new Human: pick up an item from Human group - right part - and put it in Animal group - left part - which is easily possible.

3) When we say a1.Talk(), we expect an Animal to talk. I mean we expect an Animal to act a Human behavior which is not possible.

amiry jd
  • 27,021
  • 30
  • 116
  • 215
  • so if im creating an instance of Human b1 = new Animal(); and a1.Talk() is not accessible, then what is the difference between Human b1 = new Animal(); and Animal b1 = new Animal(); – Tom Cruise Nov 05 '13 at 08:39
  • You can not create a `Human` by instantiating an `Animal`. Please read the answer carefully. An `Animal` is not a `Human`. Zebra, dog, cat, they are animals, but not human. – amiry jd Nov 05 '13 at 08:52
  • I understood According to your concept explained, its not possible. But theoretically i'm not able to convince myself what is the difference b/w Human b1 = new Animal(); and Animal b1 = new Animal(); – Tom Cruise Nov 05 '13 at 09:18
  • I can't understand what do you mean. There is no difference, because the first one doesn't exists at all. What is the difference between `Dog is an animal` and `Sun is an animal`? Or between `Dog is an animal` and `Dog is a human` or between `Dog is a human` and `Michael is a human`? In each pair, one statement is completely wrong; So we can not explain what the difference is. – amiry jd Nov 05 '13 at 09:34
  • sorry it was a typo. Please excuse..I meant what is the difference between Animal a1 = new Human(); and Animal a1=new Animal()? in both cases i can access only the method Eat. – Tom Cruise Nov 05 '13 at 09:41
  • @Javad_Amiry: What is a difference between Animal a1 = new Human(); And Animal a1=new Animal() ? – Ardalan Shahgholi Mar 17 '16 at 20:20
  • @ArdalanShahgholi OK. the question got old, But: It's all about `a1`'s behaviors. When you say `Human a1`, you expect it behave as a human. So, any client that need a human, can work with -not need to mention to animal clients; It's obvious ;) e.g. it's mom can ask him/her to talk. But, when you say `Animal a1`, it cannot act as a human. e.g. it cannot talk. But, why we do that? Cause: there are some clients that need to `Eat()` it, not to `Talk()`. So Creating `Animal a1 = new Human()` makes it possible to pass the `a1` to them. They just need to call `a1.Eat`, and a human obviously can eat. – amiry jd Mar 18 '16 at 22:57
3

Probably inheritance and polymorphism concepts are not so clear for you yet. This article may help you.

If class b inherits from a, you can imagine it as a "specialization" of a. So you can easily understand that b can be used/seen as an a instance, but the reverse is not true!


Why Im getting error in 2nd line?

because b b1 = new a(); is not a valid assignment. As explained, you can assign inherited class instance to base class variable, but not the contrary!

what is meant by a a1=new b();

this assignment is correct because you can surely use a more specific class instance as a base class instance.

why a1.testb() is not accessible even though constructor of b is assigned to a1?

when you inherit from a class, all the public and protected methods of this class are inherited and you can access or override that in the new class. but testb() is not an inherited method. is a new method defined inside class b so you can use it only if you do this assignment: b b1=new b();

davioooh
  • 23,742
  • 39
  • 159
  • 250
  • But here i created the constructor of class b and assigned to the instance a1 in the line a a1=new b(); then why methods of b is not accessible to a1 ? so do you mean to say a1=new a() and a1=new b() are same? – Tom Cruise Nov 05 '13 at 09:26
  • beacuse methods implemented in class `b` can be invoked **only** on instances of class `b`. even if you instantiate a `new b()`, you are assigning it to a `a` variable, so only methods defined in class `a` are accessible. – davioooh Nov 05 '13 at 09:35
  • so a1=new a() and a1=new b() are same? – Tom Cruise Nov 05 '13 at 09:37
  • 1
    I try to explain: if you have an instance of `b` and you assign it to a `b` variable (`b b1 = new b()`) you can use all the methods defined in `b`, and also all the methods inherited from `a`. on the other hand if you make this assignment `a a1 = new b()` you still have a `b` instance, but you reference it by an `a` variable, so you can use only methods defined in `a`. `a1=new a()` and `a1=new b()` are NOT the same, but `a1` will have the same behaviour. – davioooh Nov 05 '13 at 09:58
1

If you defined a a1 = new b() , to use methods declared in b you can cast a1 as b

 a a1 = new b();
 ((b)a1).testb();
DeveloperX
  • 4,633
  • 17
  • 22
  • so even though assigned constructor of b i will not able to access b's method using a1? then what is the meaning of creating instance of a class? – Tom Cruise Nov 05 '13 at 08:01
  • at run time instance of variable will be created ,before that compiler considers a1 as type of a and excepts you to use all methods and other stuff declared in type a – DeveloperX Nov 05 '13 at 08:05
  • @user833985 you can have multiple classes derived from `a` but want to store them in one place(list or array) so you create the storage for the base class and put everything there. Later if you want to use the functionality of derived classes you cast references like this: `b bInst = (b)aInstance;`. And you can get benefits [virtual methods](http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx) having reference to the base class but in fact having instance of one of the derived. – Guru Stron Nov 05 '13 at 08:17
1

Think of your classes as a contract, guaranteeing the existence of certain operations. Class a defines one operation, class b inherits all operations from a and defines another one of its own.

The first line:

a a1 = new b();

Declares a variable named a1 of type a, meaning whatever value you give this variable should have all the operations type a requires. new b() creates a new instance of class b, which is assigned to variable a1. Since class b inherits all operations from type a, a value of type b can be assigned to a variable of type a.

On the second line:

b b = new a();

Similarly, you define a variable which should have all the operations defined by type b. But since you put in a value of type a which doesn't define the testb operation type b requires, the compiler doesn't accept this.

As for your third question, the compiler only knows the type of your variable (a), not which value you actually assigned to it. You basically told the compiler "I guarantee this value will define the testa operation. Now let it do operation testb!" The compiler doesn't know the actual value of the variable, so as far as it's concerned, that's not possible.

As for the difference between a a1=new a() and a a1=new b(): In both cases, a variable of type a is created. In the first expression, the value assigned to this variable is a newly created instance of type a, while in the second, the value is a newly created instance of type b. Since type 'b' is basically an expanded version of type a, the compiler know that everything you could ask of an instance of type a can also be satisfied by an instance of type b, so it just treats the value as if it is of type a.

Rik
  • 28,507
  • 14
  • 48
  • 67
  • Thanks for providing me a detailed explanation. Can you tell me what the left part and right part of a a1=new b() does? is it creating an instance of a and assign constructor of b() or something similar? – Tom Cruise Nov 05 '13 at 09:20
  • @user833985 No, it creates an instance of `b` and assigns it to variable `a`. I've expanded my description of the line in question above. – Rik Nov 05 '13 at 09:46
0

1) Every b is an a but the converse is not true.

2) is an example of Polymorphism Polymorphism - Define In Just Two Sentences

3) a1.testb() is not accessible because you are treating it as an instance of a which has no definition for testb()

Community
  • 1
  • 1
David Pilkington
  • 13,528
  • 3
  • 41
  • 73