473,396 Members | 2,036 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Interfaces/multiple inheritance/restricted inheritance in .NET

Hi,

We're in the process of setting up a class hierarchy, but are encountering some issues. We wondered whether any of you with more experience might be able to lend a hand, please?

At present, we have an abstract base class called Entity. Inheriting from this are ClassA, ClassB and ClassC. The vast majority of properties/methods in Entity are usable in all child classes. However, we come across some instances as below:

Entity has the method Move(). ClassA and ClassC can be moved, but ClassB cannot.

Do you have any advice for an appropriate way to implement this, please? We have looked at:

1) Having all the code in Entity, and then in ClassB.Move() throwing a NotImplemented exception. This is not ideal because the code compiles, but only dies at runtime.

2) Having an IMovable interface that contains the Move() function, and is implemented by ClassA and ClassC:
a) with the Move code defined in both classes - not ideal because of code duplication
b) with the Move code defined in a static Helper class and called within each class - not ideal if the method signature ever has to be changed
c) with the Move code defined as a protected method in Entity, with ClassA and ClassC calling base.Move() - not ideal for the same reason as above

Thanks in advance for any advice,

Liz
Jul 20 '10 #1
7 1916
I think a mixture of 1 and 2.

ClassA should either:
* Implement IMoveable (because presumably you are going to use IMoveables in method signatures?)
* Throw a NotImplementedException and use an #error preprocessor directive to stop it from compiling.

In VB, you can't implicitly implement the interface, so this won't work, but it should work in C#. If you need to use VB, then implement IMoveable in Entity. However, this stops being compile-safe.

Jez
Jul 20 '10 #2
GaryTexmo
1,501 Expert 1GB
Even having IMovable means you'll have to duplicate the implementation in ClassA and ClassC. Perhaps ClassB should actually be the base class, or another step along the way? What about...

Expand|Select|Wrap|Line Numbers
  1. public class Entity { ... }
  2. public interface IMovable { // defines Move() }
  3. public class MovableEntity : Entity,IMovable { // implements Move() }
  4.  
  5. public class ClassA : MovableEntity { ... }
  6. public class ClassB : Entity { ... }
  7. public class ClassC : MovableEntity { ... }
Something like that?
Jul 20 '10 #3
You can write the implementation code in Entity and then implicitly implement IMoveable in the child classes without any duplication.

Changing the hierarchy would work if IMoveable is a one off, but if it is one of a number of possible options (e.g. IRoatable, ISpinable etc), then you'd this wouldn't work.

Another option would be to have Move/Rotate etc as static functions (on Entity or on a static helper class). The functions would take an IMoveable. The correct classes then implement IMoveable, which is an interface with the properties needed to run the code (again just defined once in Entity). This is probably the cleanest way of doing it.
Jul 21 '10 #4
GaryTexmo
1,501 Expert 1GB
You can write the implementation code in Entity and then implicitly implement IMoveable in the child classes without any duplication.
How do you do this without a class higher up the hierarchy getting that method? I don't think you can hide methods from the inheritance tree... maybe I don't know what you mean.

Changing the hierarchy would work if IMoveable is a one off, but if it is one of a number of possible options (e.g. IRoatable, ISpinable etc), then you'd this wouldn't work.
You can use multiple inheritance with interfaces

Expand|Select|Wrap|Line Numbers
  1. public MovableEntity : Entity,IMovable,IRotatable,IScalable { ... }
Jul 21 '10 #5
Hi Gary,

My initial suggestion was based around the fact that the "vast majority" of child classes would need the methods. Thus the idea of using the #error preprocessor directive to stop the few unwanted classes from having the method. It's not ideal, but I'd say it's about the same level of undesirability as having duplicated code in every child class. I am aware that it's still not complier safe.

My issue with having the multiple inheritance routes you suggested was that if you had various features that needed distributing to different objects, you would once again end up with duplication. So you would need an implementation of Move(), but then two implementations of Rotate() depending on whether the class can move+rotate or just rotate.

To modify your code slightly...

Expand|Select|Wrap|Line Numbers
  1. public class Entity { ... }
  2.  
  3. public interface IMovable { // defines Move() }
  4. public class MovableEntity : Entity,IMovable { // implements Move() }
  5.  
  6. public interface IRotatable { // defines Rotate() }
  7. public class RotatableEntity : Entity,IRotate { // implements Rotate() }
  8.  
  9. public class MovableAndRotatableEntity : Moveable, IRotate { // implements Rotate() }
  10.  
  11. public class ClassA : Entity { ... }
  12. public class ClassB : MovableEntity { ... }
  13. public class ClassC : RotatableEntity { ... }
  14. public class ClassD : MovableAndRotatableEntity { ... }
  15.  
I think static methods, with IMoveble/IRotatable interfaces exposing necessary methods/properties for use in the Move()/Rotate() functions is the best way forward.
Jul 21 '10 #6
GaryTexmo
1,501 Expert 1GB
Yea, you could do that I guess, but I wouldn't recommend it. Typically I would have organized them together (as I posted above) since if you want an object that moves, having support for rotation and scaling is also appropriate.

That's generally how I organize my projects that work this way (ie, game stuff) and it works out fairly well for me. Of course, just 'cause that's how I do it doesn't mean it's how everybody else does it! ;)

Static methods on Entity, which take another entity are definitely an option too. Personally I'm not a fan because the functionality for the object isn't contained within the object itself (ie, I like the object to move itself), but that doesn't make it wrong.

Hopefully between the two of us, we've provided enough to help the original poster figure out their problem :)
Jul 21 '10 #7
Joseph Martell
198 Expert 128KB
I watched a video here about game development on the android platform. The speaker actually mentioned this exact predicament. The more methods that need to be included/excluded but do not necessarily depend on each other, the more complex the inheritance hierarchy gets.

If some objects are movable and some are not, then it can be argued that "move()" is not a valid method to include in the base class because not all sub-objects will obey the same interface. Using inheritance as the go-to solution means that every new possible combination of methods requires a new inheritance chain.

The proposed solution in the video was to rely on composition instead of inheritance. Basically, you define a movable component and if an object is movable, then you give it a movable component. If an object is displayable, then you give it a displayable object. It is a big shift in paradigm from inheritance. The objects aren't polymorphic like they are when using inheritance (although each component is) so the program structure must be handled differently.

The plus side is that components can be added to and removed from an object at run-time to modify behavior. It also becomes simpler to do things like a subscriber pattern or factory patterns because each possible behavior is isolated.

Its just a thought. This doesn't work in all cases, but if inheritance is proving to be very difficult and overly complex, it might be worth exploring the composition option.
Jul 22 '10 #8

Sign in to post your reply or Sign up for a free account.

Similar topics

1
by: John | last post by:
Hi, I am trying to create a class heirarchy similar to the following: // base interface class ICar { public: virtual void start() = 0; }; // add members to that interface, but retain base...
6
by: Stuart Golodetz | last post by:
Hi, I've got a minor casting issue which I need to check about (marked // <--). I was trying to do a static_cast on it (which didn't work, though I'm not sure why this should be the case?) I...
21
by: Franco Gustavo | last post by:
Hi, Please help me to understand this, because I don't see what I'm missing. I was reading a lot of examples on Internet that explain that C# doesn't implement multiple inheritance it...
9
by: Code4u | last post by:
My colleagues and I have been discussing techniques for implementing interfaces in C++. We're looking for a mechanism similar to COM's QueryInterface, in which a certain types of objects can be...
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
0
by: Laharl | last post by:
This is what I am trying to do: public abstract class A : ISerializable { public A(SerializationInfo info, StreamingContext context){} public void GetObjectData(SerializationInfo info,...
30
by: Frank Rizzo | last post by:
We are having one of those religious debates at work: Interfaces vs Classes. My take is that Classes give you more flexibility. You can enforce a contract on the descendant classes by marking...
29
by: MAHESH MANDHARE | last post by:
Hi , Can Anyone explain me exactly why multiple inheritance not used in java and c# thanks, Mahesh -- Have A Good Day, Mahesh, Maheshmandhare@yahoo.co.in
3
by: Rich | last post by:
Hi, I want to use 2 master pages, one for the main part of the site, the other for the admin pages. They are quite similar, with many shared elements. Ideally I would like to have a parent...
0
by: Ge Chunyuan | last post by:
hi: Just out of curiosity, more than 10 years passed since Stanley B. Lippman's <<Inside the C++ Object Model>>. Is there anything changed these days? Eg, the "Memory Layout for Multiple...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.