Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Multi
I'm designing a project management system, and the WBS structure is one of the core functions.
 
I define Node as a abstract class, TreeNode class and SensitiveNode class as a subclass of Node. TreeNode reprensets a node of a tree structure, SensitiveNode reprensets a node which can do validate and log when client access it. What if I want a SensitiveTreeNode which share the behavior of both TreeNode and SensitiveNode? How can I design the class SensitiveTreeNode.
 
Because TreeNode and SensitiveNode is kind of complex, I don't want rewrite code in SensitiveTreeNode, because it would cause maintain disaster.
 
I think multi inheritation is very common in real world, what do people deal with those kind of scenarious normally.
Posted 17-Jun-11 0:17am
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

If both operations are complex and can't be arranged into a single inheritance hierarchy, you should compose, not inherit. Take out the main features of each part into a provider class, so
class SensitiveTreeNode : SensitiveNode, TreeNode {
 public void SomeSensitiveMethod(string arg) { ... }
 public TreeNode Parent { get; set; }
}
 
... becomes:
class SensitiveTreeNode : Node, ISensitiveNode, ITreeNode {
 public TreeNodeProvider TreeProvider {get; private set; }
 public SensitivityProvider SensitivityProvider { get; private set; }
 
 SensitiveTreeNode() {
  TreeProvider = GetTreeNodeProvider();
  SensitivityProvider = GetSensitivityProvider();
 }
 
 virtual TreeNodeProvider GetTreeNodeProvider() { return new TreeNodeProvider(this); }
 virtual SensitivityProvider GetSensitivityProvider() { return new SensitivityProvider(this); }
}
 
class TreeNodeProvider {
 ITreeNode host;
 
 public ITreeNode Parent { get; set; }
 
 public TreeNodeProvider(ITreeNode host) { this.host = host; }
}
 
class SensitivityProvider {
 ISensitiveNode host;
 
 public void SomeSensitiveMethod(string arg) { ... }
 
 public SensitivityTreeNodeProvider(ISensitiveNode host) { this.host = host; }
}
 
interface ISensitiveNode {
 SensitivityProvider SensitivityProvider { get; }
}
 
interface ITreeNode {
 TreeNodeProvider TreeProvider { get; }
}
 
The providers are by their nature fairly general, as they will provide functionality for any tree or sensitive node. If you want a special implementation for a particular node class, you can create a nested class which inherits from the appropriate base provider class, and assign that to the provider property.
 
This means that all calls to tree node or sensitive node methods and properties get an extra bit of text in them:
myTreeNode.TreeProvider.Parent = myOtherTreeNode;
... and it's quite a bit of work, so it's not perfect. It is the closest thing that can reasonably be done in C# (or Java or other single-inheritance languages) to inheriting two things, though – SensitiveTreeNode now really does provide two sets of functionality, and it is all inheritable, polymorphic etc (through overriding provider classes and GetXxxProvider methods).
 
The length of this reply emphasises how, if it is at all reasonable, you should try to make at least your main inheritance hierarchy be arranged so that you don't need multiple inheritance. In the case of your example, nodes are usually expected to be bound to a particular data structure; I would expect that you could make TreeNode be a base class and have sensitivity inherit from it. (Nodes not currently in a tree can simply have a null tree/parent.) But obviously we don't have the details of your problem and that may not be appropriate.
  Permalink  
Comments
SAKryukov at 17-Jun-11 15:16pm
   
Right. My 5. Working around lack of multiple inheritance is not trivial.
--SA
RayX.Mesh at 19-Jun-11 22:54pm
   
Thanks Bob, you've predicted lots of my problems and gave a great solution. Actrually, I used a similar solution as you have gaven, after readed your suggestion, I changed my design to be more flexible. Because TreeNode is much more complex than SensitiveNode, so I created a SensitiveProvider and left TreeNode to be base class. It works good and did not take much of time. The only problem is I'm not sure if this could cause confusion, because It used both inheritance and provider pattern.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

In these situations you can follow Interface based design.
 
TreeNode inherits Node
SensitiveNode inherits Node
 
Define ITreeNode as the interface for TreeNode and ISensitiveNode as interface for SensitiveNode.
 
Then, You can define the new class SensitiveTreeNode to derieve rom Node and implement ITreeNode and ISensitiveNode.
 
I would leave the implementation details of SensitiveTreeNode to you.
One of the option is to use composition of TreeNode and SensitiveNode in SensitiveTreeNode or a clean implementation, which should be driven by your requirement.
  Permalink  
v2
Comments
SAKryukov at 17-Jun-11 15:14pm
   
That is correct, but not so trivial. My 5.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

I can feel your pain: like in Java (and opposite to C++), you cannot have multiple inheritance in C# (and many many folks here think it's C# a feature, not a limitation...).
The common escape is probably inheriting from the more complex class and implementing the less complex (that should become an interface).
  Permalink  
Comments
arathi_suresh at 17-Jun-11 7:56am
   
yes..you should be using interfaces in such cases
SAKryukov at 17-Jun-11 15:19pm
   
Of course. What we have in Java and .NET is called "weak form of multiple inheritance". The advice is good, my 5, but it should be combined with using interfaces; and approach demonstrated by Bob (I think you mean something like that). Using multiple inheritance even when it is fully available is not trivial as well. May be that's why it is not used in Java, .NET and other frameworks.
 
The issue is the whole OOP approach, its inherent problem.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 280
1 Sergey Alexandrovich Kryukov 279
2 CPallini 205
3 Maciej Los 197
4 Afzaal Ahmad Zeeshan 160
0 OriginalGriff 5,635
1 DamithSL 4,496
2 Maciej Los 3,942
3 Kornfeld Eliyahu Peter 3,480
4 Sergey Alexandrovich Kryukov 3,180


Advertise | Privacy | Mobile
Web01 | 2.8.141216.1 | Last Updated 17 Jun 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100