...

View Full Version : Having some problems understanding OOP concepts (C#)



BrickInTheWall
07-26-2009, 09:01 PM
Hi everybody, I need some help clearing some things up. The following code is a bit lengthy for a post but very simple...
I have 3 classes: Animal, Cow and Chicken (which are derived from the abstract class Animal).

Animal.cs:


public abstract class Animal
{
protected string name;

public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

public Animal()
{
name = "The animal with no name.";
}

public Animal(string newName)
{
name = newName;
}

public void feed()
{
Console.WriteLine("{0} has been fed.", name);
}
}


Cow.cs:


public class Cow : Animal
{
public void Milk()
{
Console.WriteLine("{0} has been milked.", name);
}

public Cow(string newName) : base(newName)
{
}
}


Chicken.cs:


public class Chicken : Animal
{
public void LayEgg()
{
Console.WriteLine("{0} has laid an egg.", name);
}

public Chicken(string newName) : base(newName)
{
}
}


and here the main project file:
program.cs:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ch11Ex01
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Create an Array type collection of Animal objects and use it.");

Animal[] animalArray = new Animal[2];
Cow myCow = new Cow("Deirdre");
Chicken myChicken = new Chicken("Ken");
animalArray[0] = myCow;
animalArray[1] = myChicken;

foreach (Animal myAnimal in animalArray)
{
Console.WriteLine("New {0} object added to Array collection, Name = {1}.", myAnimal.ToString(), myAnimal.Name);
}

Console.WriteLine("Array collection contains {0} objects.", animalArray.Length);

animalArray[0].feed();
((Chicken)animalArray[1]).LayEgg();
Console.WriteLine();

Console.WriteLine("Create an ArrayList type collection of Animal objects and use it:");
ArrayList animalArrayList = new ArrayList();
Cow myCow2 = new Cow("Hayley");
animalArrayList.Add(myCow2);
animalArrayList.Add(new Chicken("Roy"));

foreach (Animal myAnimal in animalArrayList)
{
Console.WriteLine("New {0} object added to ArrayList collection, Name = {1}.", myAnimal.ToString(), myAnimal.Name);
}
Console.WriteLine("ArrayList collection contains {0} objects.", animalArrayList.Count);
((Animal)animalArrayList[0]).feed();
((Chicken)animalArrayList[1]).LayEgg();
Console.WriteLine();

Console.WriteLine("Additional manipulation of ArrayList:");
animalArrayList.RemoveAt(0);
((Animal)animalArrayList[0]).feed();
animalArrayList.AddRange(animalArray);
((Chicken)animalArrayList[2]).LayEgg();
Console.WriteLine("The animal called {0} is at index {1}.", myCow.Name, animalArrayList.IndexOf(myCow));
myCow.Name = "Janice";
Console.WriteLine("The animal is now called {0}.", ((Animal)animalArrayList[1]).Name);

Console.ReadKey();
}
}
}



What I mainly don't understand is the following:
1) The array Animal[] animalArray = new Animal[2]; contains objects created by Animals derived classes...how is the possible? This seems a bit like when you have pointers to the base class in an array in C++ (not really I know but thats what it reminds me of) and I don't understand why this is possible...let alone creating an array of a class type that is abstract.

2) The type conversions in some lines of the code are irritating me as I don't understand the full reason as to why this conversion is necessary. Like here:
((Chicken)animalArray[1]).LayEgg();

Any help on these two question I would really appreciate!
Cheers,
Chris

oracleguy
07-26-2009, 09:47 PM
What I mainly don't understand is the following:
1) The array Animal[] animalArray = new Animal[2]; contains objects created by Animals derived classes...how is the possible? This seems a bit like when you have pointers to the base class in an array in C++ (not really I know but thats what it reminds me of) and I don't understand why this is possible...let alone creating an array of a class type that is abstract.

Thats because Animal[] animalArray = new Animal[2] does not instantiate any Animal classes. You are creating an array of the Animal type only.

If you were do look at the value of animalArray[0] (or any other valid index) after that line, you'd see that they are null.

Animal[] animalArray = new Animal[2] is like doing this in C++:


Animal** animalArray = new Animal*[2];


Where you are creating an array of pointers.




2) The type conversions in some lines of the code are irritating me as I don't understand the full reason as to why this conversion is necessary. Like here:
((Chicken)animalArray[1]).LayEgg();

You have to convert the object to a Chicken because Animal doesn't have a LayEgg function.

BrickInTheWall
07-27-2009, 11:45 AM
Okay thanks I think I get it. So I guess making an array of type Animal would be similar to this:
Animal someAnimal;
Whereas animal is the abstract class and someAnimal is currently null.
This wouldn't work: Animal someAnimal = new Animal(); But the line above would.
Also, did you use the array of pointers as an example because an array of references is illegal in C++? Cause the way I understood things, objects in C# are reference types, so it would be like having an array of references. These lines for example:


Cow myCow = new Cow("Deirdre");
Chicken myChicken = new Chicken("Ken");
animalArray[0] = myCow;
animalArray[1] = myChicken;

could be changed to


Cow myCow = new Cow("Deirdre");
animalArray[0] = myCow;
animalArray[1] = new Chicken("Ken");

and then animalArray[1] would actually not have a reference to some other object like animalArray[0], right?

oracleguy
07-27-2009, 04:00 PM
and then animalArray[1] would actually not have a reference to some other object like animalArray[0], right?

Yes in that case the object that was just created would only be currently referenced by animalArray[1].

animalArray[0] and myCow both point to the same object.

BrickInTheWall
07-27-2009, 05:17 PM
If I have two objects obj1 and obj2 and for example assign obj1 = obj2, I cannot do anything with what was originally obj1 (if I understand correctly). So if there was nothing referencing obj1 before, would the object then be destroyed? Cause I wouldn't know how to get any of that data back cause I don't know its adress. The way I like to think of it is that you are always assigning an "adress" to the memory place where the object is, when doing something like obj1 = obj2. For example is obj1 now contains the adress to obj2, then doing obj3 = obj1 would lead to obj3 now having the adress to obj2. For all I know, variables like obj1 etc. are nothing but containers for adresses to objects. This would make sence why creating a "container" of an abstract class would be possible, aslong as it contains the adress to a valid instantiated object.

oracleguy
07-27-2009, 05:51 PM
If I have two objects obj1 and obj2 and for example assign obj1 = obj2, I cannot do anything with what was originally obj1 (if I understand correctly). So if there was nothing referencing obj1 before, would the object then be destroyed? Cause I wouldn't know how to get any of that data back cause I don't know its adress. The way I like to think of it is that you are always assigning an "adress" to the memory place where the object is, when doing something like obj1 = obj2. For example is obj1 now contains the adress to obj2, then doing obj3 = obj1 would lead to obj3 now having the adress to obj2. For all I know, variables like obj1 etc. are nothing but containers for adresses to objects. This would make sence why creating a "container" of an abstract class would be possible, aslong as it contains the adress to a valid instantiated object.

Yes, once an instantiated reference type (like a class) has no variables referencing it, it is destroyed. That is how the garbage collector knows what stuff can be deleted.

BrickInTheWall
07-27-2009, 06:11 PM
Ok thanks for the help so far, a lot is clearing up for me now. I think it's easier for me to just think of variables created from classes as pointers.

Also, if I understood correctly, if I have an object created from a base class(objA) and one created by one of its child classes(objB), then assigning objB = objA would require and explicit cast, whereas objA = objB is an implicit cast.

I think its amazing to see that my destructor (which prints something on the screen) executes when I do the following :P:


Class1 obj1 = new Class1(20);
Class1 obj2 = new Class1(30);
obj1 = obj2;


Thanks for putting up with me so far :D

oracleguy
07-27-2009, 07:02 PM
Ok thanks for the help so far, a lot is clearing up for me now. I think it's easier for me to just think of variables created from classes as pointers.

Also, if I understood correctly, if I have an object created from a base class(objA) and one created by one of its child classes(objB), then assigning objB = objA would require and explicit cast, whereas objA = objB is an implicit cast.

I think its amazing to see that my destructor (which prints something on the screen) executes when I do the following :P:


Class1 obj1 = new Class1(20);
Class1 obj2 = new Class1(30);
obj1 = obj2;


Thanks for putting up with me so far :D

Yeah you can think of them as pointers because that's basically what is going on behind the scenes.

Don't always count on the destructor firing then, it is up to the garbage collector to decide when to destroy the objects.

BrickInTheWall
07-27-2009, 11:03 PM
thanks for the quick and great replies :D. I think its incredibly confusing if I should think of reference type like working with pointer or references in C++...For me, they work more like reference types since when sending a reference type to a function it doesn't seem like there is a copy being made (unlike when sending a pointer to a function)...In C++ references seem more like an "alias" to me...whereas is seems like reference types in C# seem to be pointing to some place in the memory...or are you actually copying a hidden pointer which points to some place in the memory (heap I suppose) *head explodes*
Anyways, thanks for the help!



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum