The problem you describe could be solved using the Visitor pattern (everything can be solved using the Visitor pattern, so beware! ) The visitor pattern lets you move the implementation logic towards a new class. That way you do not need a base class, and a visitor works extremely well over different inheritance trees To sum up: New functionality does not need to be added to all different types The call to the visitor can be pulled up to the root of each class hierarchy For a reference, see the Visitor pattern.
The problem you describe could be solved using the Visitor pattern (everything can be solved using the Visitor pattern, so beware! ) The visitor pattern lets you move the implementation logic towards a new class. That way you do not need a base class, and a visitor works extremely well over different inheritance trees.To sum up: New functionality does not need to be added to all different types The call to the visitor can be pulled up to the root of each class hierarchy For a reference, see the Visitor pattern.
This pattern looks very useful, but I believe I would still need to implement OnReadyToFly() and OnReadyToLand() for every single class, because they are declared as private. How do I enforce that implementations are provided for both of these methods? – DanM Feb 22 '10 at 22:57.
Cant we use extension methods for this public static void OnReadyToFly(this IFlyBehavior flyBehavior) { _flyBehavior.Fly() } This mimics the functionality you wanted (or Mixins) Cheers.
Mixin" is the word that came to my mind, too. Ruby has them. C++ can do them using the Curiously Recurring Template Pattern and multiple inheritance.
Doesn't C# do multiple inheritance? – xtofl Feb 22 '10 at 11:50 @xtofi, C# doesn't support multiple class inheritance, but support interface level multiple inheritance.. – RameshVel Feb 22 '10 at 11:54 2 Ignoring the typo in both variable names: This fails to take into account that the classes are using composition: Your Bird is no IFlyBehavior, it just has one. Which takes you back to the start: You'd need to add a delegating method on each class (or expose the behavior directly).
– Benjamin Podszun Feb 22 '10 at 14:09.
Visual Studio already offers this in 'poor mans form' with code snippets. Also, with the refactoring tools a la ReSharper (and maybe even the native refactoring support in Visual Studio), you get a long way in ensuring consistency. EDIT: I didn't think of Extension methods, this approach brings you even further (you only need to keep the _flyBehaviour as a private variable).
This makes the rest of my answer probably obsolete... However; just for the sake of the discussion: how could this be improved? Here's my suggestion. One could imagine something like the following to be supported by a future version of the C# compiler: // keyword 'pattern' marks the code as eligible for inclusion in other classes pattern WithFlyBehaviour { private IFlyBehavior_flyBehavior; private void OnReadyToFly() { _flyBehavior.Fly(); } patternmethod private void OnReadyToLand() { _flyBehavior.Land(); } } Which you could use then something like: // probably the attribute syntax can not be reused here, but you get the point UsePattern(FlyBehaviour) class FlyingAnimal { public void SetReadyToFly(bool ready) { _readyToFly = ready; if (ready) OnReadyToFly(); // OnReadyToFly() callable, although not explicitly present in FlyingAnimal } } Would this be an improvement?
Probably.Is it really worth it? Maybe...
Regarding your edit: I don't think extension methods solve anything. They are static for one and the behavior is a private field. You cannot access the behavior in a static method on the type (and would need several of them, in the sample for Animal and PeopleMover at least).
What am I missing? – Benjamin Podszun Feb 22 '10 at 14:24 I agree with @benjamin about extension methods--they won't work for this case--but +1 for your proposal for how a pattern might be implemented. Thanks.
– DanM Feb 22 '10 at 23:05.
You just described aspect oriented programming. One popular AOP implementation for C# seems to be PostSharp (Main site seems to be down/not working for me though, this is the direct "About" page). To follow up on the comment: I'm not sure if PostSharp supports it, but I think you are talking about this part of AOP: Inter-type declarations provide a way to express crosscutting concerns affecting the structure of modules.
Also known as open classes, this enables programmers to declare in one place members or parents of another class, typically in order to combine all the code related to a concern in one aspect.
The OP wants to add a method OnReadyToFly() to his class, which must obiously be callable at compile-time. AFAIK you can't achieve this with PostSharp. – jeroenh Feb 22 '10 at 11:18 I understood his question as "a way to add the delegation to the behavior to all classes", which could be done by a pointcut.
Reading it again I'm not sure if I got that right though - not my native language and it doesn't seem to be clear. Thanks for pointing that out. – Benjamin Podszun Feb 22 '10 at 11:26 Benjamin, I believe @jeroenh is correct.
The key to my question is that OnReadyToFly() and OnReadyToLand() are private. They must be implemented within every class that follows the pattern. I believe that, with C# as it is today, this cannot be enforced.
I could forget to implement one or both of these methods and I would receive no error or warning. I also can't "auto implement" these methods, as I could if they were part of an interface. – DanM Feb 22 '10 at 23:02 Well, a compile-time weaver could in theory add them (again, using the AOP idea).
I do have to admit that my research after the initial answer showed, that AOP in the . Net world is seriously lacking. I guess this isn't of much use then, sorry.
– Benjamin Podszun Feb 22 '10 at 8:06 My question really wasn't to find a solution to my problem, it was to ask whether C# should be improved. Maybe aspect-oriented features should be added to C# as well. – DanM Feb 22 '10 at 2:00.
Could you get this sort of behavior by using the new ExpandoObject in . NET 4.0?
Interesting, Nick. I don't have . NET 4.0 yet, so I can't experiment with it, but it sounds like what it does is change the "shape" of objects at runtime.
That's very cool (I look forward to playing with it), and it very well might work, but it's not really what I'm attempting to do here. I mean, if I were going to go this route, I wonder if I wouldn't be even better off just doing some code-generation. I know the exact code I need at runtime, I just don't want to type it (or copy/paste it) a hundred times.
– DanM Feb 23 '10 at 19:25.
I will use extension methods to implement the behaviour as the code shows. Let Bird and Plane object implement a property for IFlyBehavior object for an interface IFlyer public interface IFlyer { public IFlyBehavior FlyBehavior } public Bird : IFlyer { public IFlyBehaviour FlyBehavior {get;set;} } public Airplane : IFlyer { public IFlyBehaviour FlyBehavior {get;set;} } Create an extension class for IFlyer public IFlyerExtensions { public void OnReadyToFly(this IFlyer flyer) { flyer.FlyBehavior.Fly(); } public void OnReadyToLand(this IFlyer flyer) { flyer.FlyBehavior.Land(); } }.
You forgot to use the IFlyer instance: flyer.FlyBehavior.Fly() – jeroenh Feb 22 '10 at 23:14 Thanks jeroenh! Make the correction – Sachin Feb 23 '10 at 10:46 1 should read the question fully. Private methods, dude.Private.
– Sky Sanders Feb 23 '10 at 19:52 @SkySanders : The question is whether mixins would be useful. My answer is Yes. Above, I am showing the best way of achieving behaviour with c# 3.5.Yes I am using public methods but you can avoid repititive code and add additional behaviour.
– Sachin Feb 24 '10 at 12:19.
Scala traits were developed to address this kind of scenario. There's also some research to include traits in C#. UPDATE: I created my own experiment to have roles in C#.
Take a look.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.