Go Back   CodingForums.com > :: Computing & Sciences > Computer Programming

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 07-26-2009, 09:01 PM   PM User | #1
BrickInTheWall
Regular Coder

 
BrickInTheWall's Avatar
 
Join Date: Mar 2009
Location: Munich, Germany
Posts: 139
Thanks: 1
Thanked 13 Times in 13 Posts
BrickInTheWall is on a distinguished road
Having some problems understanding OOP concepts (C#)

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:
Code:
    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:
Code:
    public class Cow : Animal
    {
        public void Milk()
        {
            Console.WriteLine("{0} has been milked.", name);
        }

        public Cow(string newName) : base(newName)
        {
        }
    }
Chicken.cs:
Code:
    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:
Code:
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
BrickInTheWall is offline   Reply With Quote
Old 07-26-2009, 09:47 PM   PM User | #2
oracleguy
Rockstar Coder


 
Join Date: Jun 2002
Location: USA
Posts: 9,042
Thanks: 1
Thanked 322 Times in 318 Posts
oracleguy is a jewel in the roughoracleguy is a jewel in the roughoracleguy is a jewel in the rough
Quote:
Originally Posted by BrickInTheWall View Post
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++:
Code:
Animal** animalArray = new Animal*[2];
Where you are creating an array of pointers.


Quote:
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.
__________________
OracleGuy
oracleguy is offline   Reply With Quote
Old 07-27-2009, 11:45 AM   PM User | #3
BrickInTheWall
Regular Coder

 
BrickInTheWall's Avatar
 
Join Date: Mar 2009
Location: Munich, Germany
Posts: 139
Thanks: 1
Thanked 13 Times in 13 Posts
BrickInTheWall is on a distinguished road
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:
Code:
Cow myCow = new Cow("Deirdre");
Chicken myChicken = new Chicken("Ken");
animalArray[0] = myCow;
animalArray[1] = myChicken;
could be changed to
Code:
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?

Last edited by BrickInTheWall; 07-27-2009 at 11:48 AM..
BrickInTheWall is offline   Reply With Quote
Old 07-27-2009, 04:00 PM   PM User | #4
oracleguy
Rockstar Coder


 
Join Date: Jun 2002
Location: USA
Posts: 9,042
Thanks: 1
Thanked 322 Times in 318 Posts
oracleguy is a jewel in the roughoracleguy is a jewel in the roughoracleguy is a jewel in the rough
Quote:
Originally Posted by BrickInTheWall View Post
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.
__________________
OracleGuy
oracleguy is offline   Reply With Quote
Old 07-27-2009, 05:17 PM   PM User | #5
BrickInTheWall
Regular Coder

 
BrickInTheWall's Avatar
 
Join Date: Mar 2009
Location: Munich, Germany
Posts: 139
Thanks: 1
Thanked 13 Times in 13 Posts
BrickInTheWall is on a distinguished road
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.

Last edited by BrickInTheWall; 07-27-2009 at 05:39 PM..
BrickInTheWall is offline   Reply With Quote
Old 07-27-2009, 05:51 PM   PM User | #6
oracleguy
Rockstar Coder


 
Join Date: Jun 2002
Location: USA
Posts: 9,042
Thanks: 1
Thanked 322 Times in 318 Posts
oracleguy is a jewel in the roughoracleguy is a jewel in the roughoracleguy is a jewel in the rough
Quote:
Originally Posted by BrickInTheWall View Post
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.
__________________
OracleGuy
oracleguy is offline   Reply With Quote
Old 07-27-2009, 06:11 PM   PM User | #7
BrickInTheWall
Regular Coder

 
BrickInTheWall's Avatar
 
Join Date: Mar 2009
Location: Munich, Germany
Posts: 139
Thanks: 1
Thanked 13 Times in 13 Posts
BrickInTheWall is on a distinguished road
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:
Code:
Class1 obj1 = new Class1(20);
Class1 obj2 = new Class1(30);
obj1 = obj2;
Thanks for putting up with me so far

Last edited by BrickInTheWall; 07-27-2009 at 06:14 PM..
BrickInTheWall is offline   Reply With Quote
Old 07-27-2009, 07:02 PM   PM User | #8
oracleguy
Rockstar Coder


 
Join Date: Jun 2002
Location: USA
Posts: 9,042
Thanks: 1
Thanked 322 Times in 318 Posts
oracleguy is a jewel in the roughoracleguy is a jewel in the roughoracleguy is a jewel in the rough
Quote:
Originally Posted by BrickInTheWall View Post
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:
Code:
Class1 obj1 = new Class1(20);
Class1 obj2 = new Class1(30);
obj1 = obj2;
Thanks for putting up with me so far
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.
__________________
OracleGuy
oracleguy is offline   Reply With Quote
Old 07-27-2009, 11:03 PM   PM User | #9
BrickInTheWall
Regular Coder

 
BrickInTheWall's Avatar
 
Join Date: Mar 2009
Location: Munich, Germany
Posts: 139
Thanks: 1
Thanked 13 Times in 13 Posts
BrickInTheWall is on a distinguished road
thanks for the quick and great replies . 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!

Last edited by BrickInTheWall; 07-27-2009 at 11:13 PM..
BrickInTheWall is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 12:12 PM.


Advertisement
Log in to turn off these ads.