简体   繁体   中英

C# accessors and object class inheritance

So I have a maybe naive question about object inheritance and constructors. Basically, a class has an object:

public class ParentClass{
protected Parent item;

And the accessor goes as follows:

public Parent ItemValue
{
    set
    {
        item = value;
    }
    get
    {
        return item;
    }
}

Now I want to inherit the class:

public class ChildClass:ParentClass
    {
    public new Child item;
    }

Now, whenever I access the Child item through the inherited accessor it, of course, returns the item as the Parent class instead of Child class. Is there a way to make it return the item as Child class without overwriting the accessor in the ChildClass ?

No, you can't change type of base property to return different (derived) type.

Standard workaround if you don't need inheritance - generic class:

public class ParentClass<T> {
      public T ItemValue { get; set; }
...
}

public class ChildClass : ParentClass<ChildClass> 
{
  ...
}

Note that if you just need access to item in its own class you can just have virtual property:

public class Parent { }
public class Child:Parent { public string ChildProperty; }

public abstract class ParentClass
{
    public abstract Parent ItemValue { get; }
}

public class ChildClass : ParentClass
{
    Child item;
    public override Parent ItemValue { get {return item;} }

    public void Method()
    {
       // use item's child class properties
       Console.Write(item.ChildProperty);
    }
}

If you are just wanting to have Item of a type defined by your descendent class, you can do this

public class ParentClass<T>{
  protected T item;
  public T ItemValue
  {
    set
    {
        item = value;
    }
    get
    {
        return item;
    }
  }
}

public class ChildClass:ParentClass<Child>
{
    // No need to create a new definition of item
}

However depending on your problem, your next question will be how can I add ChildClass1 and ChildClass2 to the same List/Array/Dictionary/etc when they have different T's.

Take a step back for a minute. Does your ParentClass really need to know what item is?

(Ab)Using the Animal example above, your Horse might have a Walk(), Trot(), Canter() or Gallop() methods but a Duck might have a Swim() or Waddle() methods.

Perhaps your logic says something like, iterate my animal collection and tell the swimmers to swim. In this case, you could declare:

using System;
using System.Collections.Generic;


public class Program
{
    public class Location {}

    public interface ISwimmer{
      void SwimTo(Location destination);
    }

    public class Animal {} // whatever base class properties you need

    public class Duck : Animal, ISwimmer
    {
        public void SwimTo(Location destination)
        {
            Console.WriteLine("Implement duck's swim logic");           
        }
    }

    public class Fish : Animal, ISwimmer
    {
        public void SwimTo(Location destination)
        {
            Console.WriteLine("Implement fish's swim logic");
        }
    }

    public class Giraffe : Animal {}


    public static void Main()
    {
        List<Animal> animals = new List<Animal>
        {
            new Duck(),
            new Fish(),
            new Giraffe()
        };  

        foreach (Animal animal in animals)
        {
            ISwimmer swimmer = animal as ISwimmer;          
            if (swimmer==null) continue; // this one can't swim
            swimmer.SwimTo(new Location());
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM