0

I know how to do this in Java, but C# is not working right. I'm sure I am missing something obvious. I want to downcast Pet to Dog if the Pet is other than a Dog, as you can see. I think the downcast is right, but maybe it is not. The problem is that this line Console.WriteLine("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", Name, Type, Price, Weight, Sound(), AKCRegistration); it does not allow me to access the getters that I am referring to.

This is my Main class

        static void Main(string[] args)
        {
            Pet[] pets = new Pet[5];
            pets[0] = new Dog("King", 55, PET_TYPE.Canine, "akc1000", 1000);
            pets[1] = new Dog("Princess", 25, PET_TYPE.Canine, "akc1000", 2000);
            pets[2] = new Dog("Spike", 25, PET_TYPE.Canine, "akc1000", 25);
            pets[3] = new Cat("Missy", 15, PET_TYPE.Feline, 50);
            pets[4] = new Cat("Mr Boogangle", 5, PET_TYPE.Feline, 30);

            //for (int i = 0; i < pets.Length; i++)
            //{
            //    Console.WriteLine($"{pets[i]}");
            //}

            for each (Pet pet in pets)
            {
                if (pet is Dog)
                {
                    Dog Pet = (Dog) pet;

                    Console.WriteLine("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", Name, Type, Price, Weight, Sound(), AKCRegistration);
                }
            }

This is my Dog class

class Dog: Pet
    {
        private string aKCregistration;

        public Dog(string name, int weight, PET_TYPE type, string AKC, double price) : base(name, weight, type, price)
        {
            this.aKCRegistration = AKC;
            if (aKCRegistration == "")
            {
                aKCRegistration = "Mutt";
            }
        }

        public int AKCRegistration { get; set; }

        public override string Sound()
        {
            return "Woof, Woof";
        }

        public override string ToString()
        {
            return String.Format("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", Name, Type, Price, Weight, Sound());
        }
    }

My Pet Class

public enum PET_TYPE
    {
        Canine, Feline
    }

    public abstract class Pet
    {
        internal string name;
        internal int weight;
        internal PET_TYPE type;
        internal double price;

        public Pet(string name, int weight, PET_TYPE type, double price)
        {
            this.name = name;
            this.weight = weight;
            this.type = type;
            this.price = price;
        }

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

        public int Weight
        {
            get { return weight; }
            set { weight = value; }
        }

        public double Price
        {
            get { return price; }
            set { price = value; }
        }

        public PET_TYPE Type
        {
            get { return type; }
            set { type = value; }
        }

        public override string ToString()
        {
            return String.Format("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", Name, Type, Price, Weight, Sound());
        }

        public abstract string Sound();


    } // end class pet  

I included everything except my cat class, let me know if you need to see it.

inDepth
  • 121
  • 1
  • 13

1 Answers1

1

You are not referencing to them using the instance variable Pet in this case as you are accessing them from outside the class you need to specify the instance variable on them to tell that you are accessing the state of which object like:

Console.WriteLine("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", 
                   Pet.Name, 
                   Pet.Type, 
                   Pet.Price, 
                   Pet.Weight, 
                   Pet.Sound(), 
                   Pet.AKCRegistration);

and as you are alreading overriding the ToString member function in Dog you can also call it like:

string petString = Pet.ToString();

When you are accessing those within the class Dog it means you are referring to the current object whichever is calling the ToString method so it works without specifying any instance explicitly, you can think of it that one like:

Console.WriteLine("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", 
                   this.Name, 
                   this.Type, 
                   this.Price, 
                   this.Weight, 
                   this.Sound(), 
                   this.AKCRegistration);

but we don't need to explicitly add this as the compiler takes care of that.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • Ok so this fixed the problem. But I am having a new problem with the AKCRegistration printing 0 to the console instead of being instantiated with the string from the object, i added the place holder that was missing in `Console.WriteLine("{0,12}\t {1}\t {2,10:C}\t {3}\t {4}", Name, Type, Price, Weight, Sound(), AKCRegistration);` I tried debugging and AKCRegistration is instantiated in the constructor but still says its 0 in the main class – inDepth Oct 11 '18 at 19:42
  • do you have that defined in `Pet` ? – Ehsan Sajjad Oct 11 '18 at 19:46
  • you cannot access child class properties from parent class type reference – Ehsan Sajjad Oct 11 '18 at 19:47
  • In Java, I did not need to define it in the Pet class, that is what the downcasting was for, or at least that is what I was told. – inDepth Oct 11 '18 at 19:50
  • no you are confusing it, in java as well we cannot access child class properties in parent – Ehsan Sajjad Oct 11 '18 at 19:58
  • The super class is Pet, and its subclass is Dog and Cat. You are right that we can't access a subclasses properties inside the super class. However, that is not what I'm trying to do. I am trying to access it in the Main class, called `PetTest` – inDepth Oct 11 '18 at 20:03
  • i don't see anything like that in your code posted above, please post a new question with specifics if you have any confusion, don't spam this post – Ehsan Sajjad Oct 11 '18 at 20:05
  • I think it is pretty clearly defined above, `class Dog: Pet` and then I showed my Pet class as well as the main class. Either way, simple mistake, and I agree, lets avoid extended conversations – inDepth Oct 11 '18 at 20:09
  • Your new bug is because you have a auto getter/setter for the public AKCRegistration property but you are not actually assigning it a value ever. You are instead creating another completely separate private aKCRegistration field and assigning to that. Just delete your aKCRegistration and only reference AKCRegistration. If your intention is to keep assignment private (which is good practice), then define AKCRegistration as {get; private set;} – Chris Graham Oct 11 '18 at 20:47