Reputation: 1631
Alright, so as you probably know, static inheritance is impossible in C#. I understand that, however I'm stuck with the development of my program.
I will try to make it as simple as possible. Lets say our code needs to manage objects that are presenting aircrafts in some airport. The requirements are as follows:
There are members and methods that are shared for all aircrafts
There are many types of aircrafts, each type may have its own extra methods and members. There can be many instances for each aircraft type.
Every aircraft type must have a friendly name for this type, and more details about this type. For example a class named F16 will have a static member FriendlyName with the value of "Lockheed Martin F-16 Fighting Falcon".
Other programmers should be able to add more aircrafts, although they must be enforced to create the same static details about the types of the aircrafts.
In some GUI, there should be a way to let the user see the list of available types (with the details such as FriendlyName) and add or remove instances of the aircrafts, saved, lets say, to some XML file.
So, basically, if I could enforce inherited classes to implement static members and methods, I would enforce the aircraft types to have static members such as FriendlyName. Sadly I cannot do that.
So, what would be the best design for this scenario?
Upvotes: 7
Views: 401
Reputation: 56537
An interesting way to solve this problem is to recognize that aircraft types are also an important concept in the design and create them as separate classes, whose instances act as types of aircrafts. This is known as the type object pattern (pdf), and it allows for very flexible designs.
Upvotes: 0
Reputation: 137547
@Aaronaught hit the nail on the head with the plugin-like architecture comment.
What I did the last time I encountered this, was to have a "Descriptor" type that was not terribly expensive to create, and keep the meta data in an instance field.
public class F16Descriptor : AircraftDescriptor
{
public override string Name { get { return "Lockheed Martin F-16 Fighting Falcon"; } }
public override Type AircraftType { get { return typeof(F16); } }
}
public class F16 : AircraftBase
{
...
}
Upvotes: 0
Reputation: 27515
This is a case where you may benefit from a Factory pattern. Instead of importing specific types of Aircraft, provide a standard IAircraftFactory interface that defines what every Aircraft Factory needs to do for you. This is where you can return descriptions, UI information, etc. The Aircraft Factory is then responsible for creating the particular Aircraft. Because your clients must create a custom Factory in order to expose their Aircraft, they are forced to implement the interface and reminded (via its members) that they have a contract to fulfill.
Something like:
public interface IAircraft
{
//Aircraft instance details...
}
public interface IAircraftFactory
{
//Can include parameters if needed...
IAircraft BuildAircraft();
//And other useful meta-data...
string GetDescription();
}
//In some other Client-provided DLL...
public class MyAircraftFactory : IAircraftFactory
{
IAircraft BuildAircraft()
{
return new MyAircraft();
}
//...
}
Upvotes: 2
Reputation: 9163
Don't use static methods. use instance methods instead.
Also the top abstract may expose an abstract method that will return the aircraft specific name.
public abstract class Aircraft
{
public abstract string Name { get; }
public abstract string FriendlyName { get; }
}
Upvotes: 3
Reputation: 5261
Use an enumeration for the friendly names, and create an instance member of that type for the friendly name. Require the initialization of this member during construction.
Upvotes: 1
Reputation: 29081
Why do you need these properties to be static?
public class Aircraft
{
protected string AircraftName { get; protected set; }
}
public class F16 : Aircraft
{
public F16()
{
AircraftName="F16 Falcon";
}
}
Upvotes: 4
Reputation: 122684
One answer is to decorate each class with attributes (metadata):
[Description("Lockheed Martin F-16 Fighting Falcon")]
public class F16 : Aircraft
{
// ...
}
This is using the DescriptionAttribute already in System.ComponentModel
.
You can get the metadata like this:
Type t = typeof(F16);
DescriptionAttribute attr = (DescriptionAttribute)Attribute.GetCustomAttribute(t,
typeof(DescriptionAttribute));
string description = (attr != null) ? attr.Description : t.Name;
This will get you the description text from a reference to the F16
class.
Upvotes: 8