Reputation: 733
I have a class structure for a role playing game which looks like this...
public abstract class Item
{
public abstract string Name { get; set; }
}
public abstract class Armor : Item
{
public override string Name { get; set; }
}
public class Helmet : Armor
{
public override string Name { get; set; }
}
Basically, I am trying to force every derived type to include a "Name" property. Is this the best way to do it? I know I can remove "abstract" from Item.Name and then remove the overriden "Name" properties in Armor and Helmet. If I do that the code looks a little cleaner but I might forget to set the base.Name in these derived classes.
Could someone help show me the best way to do this?
EDIT: Sorry, let me clarify my question a little more. I want to make sure of 2 things. 1) Name property exists in all derived classes 2) Name property is not null or empty
I basically want to force any class that derives from Item (and is not abstract) to have a value for Name.
Upvotes: 8
Views: 9765
Reputation: 978
i think you can still make the property virtual within a abstract class, thus that should solve your problem.
You can set the value to something specific in the base abstract class, here an example :
public abstract class Item
{
public virtual string Name
{
get {return m_strName;}
set {m_strName = value;}
}
public abstract class Armor : Item
{
public override string Name { get; set; } // if you want to override it
}
public class Helmet : Armor
{
public override string Name { get; set; } // if you want to override it
}
Upvotes: 0
Reputation: 33163
It sounds like you are worried about initialising properties?
but I might forget to set the base.Name in these derived classes.
One way the you can force the Name property to be set is to include this setter in your base class constructor like so:
public class MyBaseClass
{
private string _name;
public MyBaseClass(string name)
{
_name = name;
}
}
Then everything that derives from MyBaseClass must satisfy that constructor:
public class MyDerivedClass
{
public MyDerivedClass(string name) : base(name)
{
}
}
Then you can also make the property either:
I'm not going to venture whether the above is good design, but it would work to ensure that all derived classes have a valid name property when instantiated.
Another approach, as other answers suggest, is to implement a virtual property that throws an exception in its base implementation.
Upvotes: 9
Reputation: 13720
Mike is right that if you just want to use the property "Name" on all derived objects, you don't need it to be marked abstract at all as it's inherited.
If you want to just force the fact that when Items are created, a name is definitely set, you could force it through hiding the zero-parameter constructor and exposing a constructor that accepts the name.
Take a look at this code:
public class Item
{
public string Name { get; set; }
public Item(string name)
{
this.Name = name;
}
protected Item() {}
}
public class Armor : Item
{
public Armor(string name) : base(name) {}
protected Armor() {}
}
public class Helmet : Armor
{
public Helmet(string name) : base(name) {}
protected Helmet() {}
}
The above definitions mean that:
Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build
Armor myArmor = new Armor (); //will not build
Armor myArmor = new Armor ("Some Fancy Armor Name"); //will build
Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build
This forces that any instance of the classes must define the name at time of creation. One possible solution anyway...
Upvotes: 2
Reputation: 978
so it depends what you want to do ...
making class abstract forces all the sub-classes to implement the class (and its abstract functions, etc.), but if you want a function to have a base functionality with the possibility to override the function then i'll suggest not making the class abstract and making the specific function virtual instead, thus when the virtual function is not being overwritten, and base function will be called.
and there's always options to create a "new" properties with the same name, but i don't think that's a good practice.
hope that helps.
Upvotes: 0
Reputation: 34592
Would making Name a virtual ie. public virtual Name {get; set; }
accessor be used in the Item class? Since Helment and Armor descend from the Item class. It would enforce that they must be overridden...
Hope this helps, Best regards, Tom.
Upvotes: 0
Reputation: 60013
If I do that the code looks a little cleaner but I might forget to set the base.Name in these derived classes.
Then the name of the object will just end up being something silly.
Better yet, have name
start out as null
. Then you'll get an exception if you forget to initialize the name but someone tries to use it, and you'll know you have to fix it.
Upvotes: 2
Reputation: 17949
You only need to define Name
in the base class, and do not need to specify it as abstract. It will still be available as a property in all derived classes.
public abstract class Item
{
public string Name { get; set; }
}
public abstract class Armor : Item
{ }
public class Helmet : Armor
{ }
Upvotes: 4