helion3
helion3

Reputation: 37391

Access static constant of a subclass from the base class

I have an Animal base class and every subclass needs a static string ID for identification purposes.

So I might have:

public class Dog : Animal {
   public static readonly string ID = "dog";
}

I do this because I frequently need to use Dog.ID throughout my app - in places where I don't yet have an instance.

However, I also need to access this when I have an instance, but I only want to put something like GetId() in the base class:

public class Animal {
  public string GetId() {
    return ID;
  }
}

The problem is, Animal would not have access to the static ID field in the children.

Is there a way to do this that I've overlooked?

Upvotes: 1

Views: 400

Answers (6)

foxanna
foxanna

Reputation: 1570

If you agree to an assumption that ID equals to the type name, you can use this approach. It lets you define and inherit ID property in the base class. Though I agree this might look quite strange at first sight.

public class Animal<T> where T : Animal<T>
{
    public static readonly string ID = typeof(T).Name;
}

public class Dog : Animal<Dog>
{
}

public class Cat : Animal<Cat>
{
}

Expression Cat.ID will return Cat, and Dog.ID will return Dog.

Upvotes: 0

Marco Luongo
Marco Luongo

Reputation: 387

Implement explicit interface like this

public class Animal : IType
{
    private static string _ID = "Animal";

    string IType.ID
    {
        get
        {
            return getID();
        }
    }

    public virtual string getID()
    {
        return _ID;
    }
}
public class Dog : Animal, IType
{
    public static readonly string _dogID = "dog";
    string IType.ID
    {
        get
        {
            return _dogID;
        }
    }
    public override string getID()
    {
        return _dogID;
    }

}


....
// usage
Animal a = new Animal();
Animal d = new Dog();
Console.WriteLine(a.getID());
Console.WriteLine(d.getID());

Upvotes: 0

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

If this is a static, set-once identifier, it seems like you should use an attribute instead of a static field or property:

public class AnimalIdAttribute : Attribute
{
     public AnimalIdAttribute(string id)
     {
           Id = id;
     }

     public string Id { get; }
}

public class Animal 
{
     public string Id => this.GetCustomAttribute<AnimalIdAttribute>(true)?.Id;
}

[AnimalId("dog")]   
public class Dog : Animal
{
}

Also, if any animal should provide an Id, your Animal class should be an abstract class which should also define an abstract Id property:

public abstract class Animal
{
    // Now you can access Id property implementation 
    // from Animal
    public abstract string Id { get; }
}

public class Dog : Animal
{
    public override string Id { get; } = "dog";
}

Upvotes: 1

user6996876
user6996876

Reputation:

What about an abstract method?

public class Dog : Animal
{
    public static readonly string ID = "dog";
    public override string GetId()
    {
        return ID;
    }
}

public abstract class Animal
{
    public abstract string GetId();
}

or virtual

public class Animal
{
    public virtual string GetId()
    {
        return null;
    }
}

Upvotes: 3

Teja
Teja

Reputation: 325

Or, you can do something like this:

public class Animal
{
    public static string Id;

    public virtual string GetId()
    {
        return Id;
    }
}

public class Dog : Animal
{
    public new static readonly string Id = "dog";

    public override string GetId()
    {
        return Id;
    }
}

This gives you ability to call Id from Class or an instance.

Upvotes: 0

dana
dana

Reputation: 18145

Ugly... But you could use reflection:

FieldInfo id = GetType().GetField("ID", BindingFlags.Public | BindingFlags.Static);
return id.GetValue(null);

Upvotes: 1

Related Questions