Reputation: 927
I have looked on line for information that would help me solve a design issue that is confusing me. I am new to complicated inheritance situations so my solution could actually just be rooted in a better design. But in trying to figure out what my design should be, I keep ending up thinking I really just need to inherit more than 1 base class.
My specific case involves Assets and different types of Assets.
Starting with the Asset...
Every PhysicalDevice is an Asset
Every VirtualDevice is an Asset
Every Server is an Asset
Every PhysicalServer would need to be both a PhysicalDevice and a Server
Every VirtualServer would need to be both a VirtualDevice and a Server
Every NetDevice is a PhysicalDevice
Every StorageArray is a PhysicalDevice
One solution I guess is to duplicate the Server code for both PhysicalServers, and VirtualServers however, I feel like this goes against what im trying to do, which is inherit.
They need to be separate classes because each of the types will have properties and methods. For instance, Server will have OSCaption, Memory, Procs, etc. PhysicalDevice will have things like Location, Serial, Vendor etc. And VirtualDevice will have a ParentDevice, State, VHDLocation etc.
If the inheritance is liner then i run into the problem of not being able to describe these types accurately.
Something that seems intriguing is Interfaces. It seems that i can define all base classes as interfaces and implement them in my main classes as needed. but, I am simply unsure of what the implications are if I were to do that.
for instance, something like... PhysicalServer : IAsset : IServer : IPhysical
I am in deep water so I’m really just looking for suggestions or guidance.
Upvotes: 9
Views: 2934
Reputation: 9584
To start with remember that inheritance is the obvious result of the kind of problem that you have mentioned. Every class does have more than one behavior and everyone falls into this trap. So chill. You are not the first nor the last.
You need to modify your thinking a bit to break away from the norm.
You need to look at it from the angle of what "changes" in future rather than look at a hierarchical kind of class diagram. A class diagram may not be hierarchical instead it needs to represent "what changes" and what "remains constant". From what I see, in future you may define a MobileDevice, VirtualMobileDevice.
In your current classes you seem to have properties like Vendor, Serial. These may be needed in MobileDevice too right ? So you need to modify your thinking to actually think of behaviors instead of classes that make hierarchical sense.
Rethink, you are going down the track of multiple inheritance, very dangerous and complex design. Its not the correctness of your thought process that is in question here. Its the question of you coding something and someone up ahead in the near future complicating it beyond repair.
No multiple inheritance in java is there for this one reason, to ensure that you dont think the hierarchical way.
Think "factories" (for creation), strategy (for common functionality/processing).
Edited :
Infact you should also consider creating layers in the form of library, so that there is complete abstraction and control on the main parts of your processing. What ever you intend to do with the Asset/Device class should be abstracted into a library, which can be protected by change.
Upvotes: 0
Reputation: 5468
Use mixins.
You first decide which is the primary thing you want your object to be. In your case I think it should be server.
public class PhysicalServer : Server
Then you add interfaces for the other functionalities.
public class PhysicalServer : Server,IAsset,IVirtualDevice
And you add extension methods to the interfaces.
public static int WordCount(this IAsset asset)
{
//do something on the asset
}
Here's an article on mixins in case my answer is too simple: http://www.zorched.net/2008/01/03/implementing-mixins-with-c-extension-methods/
Upvotes: 3
Reputation: 54387
Interfaces are an appropriate way of ensuring contract integrity across types, but you may end up with duplicate code for each implementation.
Your scenario may lend itself better to composition than inheritance (or a combination thereof).
Example - Inheritance + Composition
public class PhysicalServer : Asset
{
public PhysicalInfo PhysicalProperties
{
get;
set;
}
}
public class VirtualServer : Asset
{
public VirtualInfo VirtualProperties
{
get;
set;
}
}
Example - Composition Only
public class VirtualServer
{
public VirtualInfo VirtualProperties
{
get;
set;
}
public AssetInfo AssetProperties
{
get;
set;
}
}
You could then add polymorphism/generics into the mix and create derivatives of types to represent more specific needs.
Example - Inheritance + Composition + Genericized Member that inherits from a common type
public class VirtualServer<TVirtualInfo> : Asset
where TVirtualInfo : VirtualDeviceInfo
{
public TVirtualInfo VirtualProperties
{
get;
set;
}
}
public class VirtualServerInfo : VirtualDeviceInfo
{
// properties which are specific to virtual servers, not just devices
}
There are countless ways that you could model this out, but armed with interfaces, composition, inheritance, and generics you can come up with an effective data model.
Upvotes: 8
Reputation: 5251
C# doesn't support multiple inheritance from classes (but does support multiple implementations of interfaces).
What you're asking for is not multiple inheritance. Multiple inheritance is where a single class has more than one base class. In your example each class inherits from one/zero other classes. Asset and Server being the ultimate base classes. So you have no problem doing that in c#, you can just define the functionality common in eg server and then do different things in VirtualDevice and PhysicalDevice.
However you will end up with a possibly complex class hierarchy and many people would advocate composition over inheritance. This is where you'd have interfaces defining behaviour and classes implement the interface to say that they do something but each class can implement the interface methods differently. So your example for the PhysicalServer interfaces may be encouraged.
Upvotes: 1