Reputation: 1678
I want to create an abstract base class for all paramter-type classes to inherit from in my application. All paramters will have name, ID and required properties.
All parameters will have their properties set from XML via the SetProperties method (the XmlParser class shown below is just for demonstration).
Since all parameters will have the same 3 properties, I wanted the base class to set those properties but have the inheriting class extend the SetProperties method to set the additional properties it contains.
I was thinking of something like overriding events on a Control
.
Here is a sample of what I was thinking, although it does not work.
abstract class ParameterBase
{
protected string ParameterName;
protected bool IsRequired;
protected int ParameterId;
public abstract void SetProperties(string xml)
{
this.ParameterName = XmlParser.GetParameterName(xml);
this.IsRequired = XmlParser.GetIsRequired(xml);
this.ParameterId = XmlParser.GetParameterId(xml);
}
}
abstract class Parameter1 : ParameterBase
{
private string _value;
public string ParameterName
{
get { return base.ParameterName; }
}
public bool IsRequired
{
get { return base.IsRequired; }
}
public int ParameterId
{
get { return base.ParameterId; }
}
public string Value
{
get { return _value; }
}
public Parameter1()
{
}
public override void SetProperties(string xml)
{
base.SetProperties(xml);
_value = XmlParser.GetValue(xml);
}
}
Upvotes: 0
Views: 4806
Reputation: 74267
As noted, don't over think it. I'd declare the abstract parameter class so that it has a single constructor (protected) that takes the mandatory three properties ( Name, IsRequired, and ID). This means that every concrete subtype must construct it properly.
Then, I'd have an abstract factory method, CreateInstance()
, that every concrete subtype must implement, returning an instance of AbstractParameter. Why? Read up on the Liskov Substitution Principle. In the Real World, of course, it might make more sense to, rather than use a factory method, separate the concern of how to creating parameter instances from the concerns of being a parameter, by moving the construction logic into its own factory class (AbstractParameterFactory
?).
I might note, though, that you're missing an essential property that all parameters will have: a Value. You might consider making your abstract parameter's base class generic.
Anyway, here's my AbstractParameter
class:
public abstract class AbstractParameter
{
public string Name { get ; protected set ; }
public bool IsRequired { get ; protected set ; }
public int ID { get ; protected set ; }
protected AbstractParameter( string name , bool isRequired , int id )
{
this.Name = name;
this.IsRequired = isRequired;
this.ID = id;
this.Value = default(T) ;
return;
}
public abstract AbstractParameter CreateInstance( string xml ) ;
}
A concrete parameter class that derives from AbstractParameter
might then look something like this:
public class ConcreteParameter : AbstractParameter
{
public ConcreteParameter( string name , bool isRequired , int id ) : base( name , isRequired , id )
{
return ;
}
public override AbstractParameter CreateInstance( string xml )
{
string name = XmlParser.GetName();
bool required = XmlParser.GetIsRequired();
int id = XmlParser.GetID();
ConcreteParameter instance = new ConcreteParameter( name , required , id );
return instance;
}
}
Upvotes: 0
Reputation: 10313
There are four issues with your code that I can see:
You are redefining the 3 shared properties, and you're trying to name them the same as an existing field. This is not allowed. The simplest way is to implement the properties in the base class in the same way you implemented Value
in the inheriting class: with backing fields. In C# 3.0 and above (Visual Studio 2008 and up), you can use auto-implemented properties with a private setter. This will make the compiler create the backing fields for you. For example:
public string ParameterName { get; private set; }
You are declaring the SetProperties
method as abstract
. This should be virtual
. abstract
means that the subclass must define the entire implementation. That's not the case here.
In your derived class, you override SetValues
but the method is called SetProperties
.
You are declaring Parameter1
as abstract. You can't instantiate abstract classes, so you would have to inherit a class from Parameter1
as well in order to use it. I'm guessing you would just want to remove the abstract
qualifier.
Upvotes: 1
Reputation: 112352
You are making it too complicated. The first three properties can be inhertied from the base class:
public abstract class ParameterBase
{
public string ParameterName { get; private set; }
public bool IsRequired { get; private set; }
public int ParameterId { get; private set; }
public virtual void SetProperties(string xml)
{
ParameterName = XmlParser.GetParameterName(xml);
IsRequired = XmlParser.GetIsRequired(xml);
ParameterId = XmlParser.GetParameterId(xml);
}
}
public class Parameter1 : ParameterBase
{
public string Value { get; private set; }
public override void SetProperties(string xml)
{
base.SetProperties(xml);
Value = XmlParser.GetValue(xml);
}
}
Also note that an abstract method cannot have a body, instead it is terminated by a semicolon:
public abstract void SetProperties(string xml);
You must delacre it as virtual if you want to give it a base implementation.
(And you must override SetProperties
, not SetValue
.)
Upvotes: 0
Reputation: 62246
I would do simply, like this:
abstract class ParameterBase
{
protected string ParameterName;
protected bool IsRequired;
protected int ParameterId;
public abstract void SetProperties(string xml);
}
and derived one:
public class Parameter1 : ParameterBase
{
public override void SetProperties(string sml)
{
//set properties including those ones of parent
}
}
It's easy and clearer to manage in this way. Move common properties in separate base class it's good, but persistance management (Save/Load), leave to children. They should know how to do that.
Code provided has a couple of problems:
abstract
method can not have body
you have strange public override void SetValues(string xml)
which I think should be
public override void SetProperties(string xml)
Upvotes: 4
Reputation: 2942
I would make the common Base class properties Public with protected setters, then you can access them from any derived classes, no use duplicating code!
protected string ParameterName { get; protected set; };
protected bool IsRequired { get; protected set; };
protected int ParameterId { get; protected set; };
Upvotes: 0