Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts

    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

  • #2
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    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.


    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

  • #3
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    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 12:48 PM.

  • #4
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    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

  • #5
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    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 06:39 PM.

  • #6
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    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

  • #7
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    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 07:14 PM.

  • #8
    Rockstar Coder
    Join Date
    Jun 2002
    Location
    USA
    Posts
    9,074
    Thanks
    1
    Thanked 328 Times in 324 Posts
    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

  • #9
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    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-28-2009 at 12:13 AM.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •