I have a DLL, that we bought and I can't access its source. However, for the problem that I'm now facing, I've been told that I must inherit from a class in the DLL, and override one of its methods.
I tried it and it works quite well, as expected. My problem now is that I have quite a few classes where I need to do the same thing, and don't want to repeat the same code so many times. Although all of those classes inherit from the same DLL class, it doesn't look good to me to write the same code in all of them.
This is the code for one class:
public class MyClass : DllClass
{
protected override void MethodFromDll()
{
//here I inserted my code and it works ok
}
}
Thanks
Why not create an abstract class which derives from DllClass and override the method there, then derive your other classes from that?
public abstract class MyClassBase : DllClass
{
protected override void MethodFromDll()
{
//here I inserted my code and it works ok
}
}
...
public class MyClass : MyClassBase
{
// Whatever else you need
}
That's assuming you need inheritance here in the first place - do you definitely need to have multiple derived classes, or could you have lots of classes which use MyClass by composition instead?
Related
I'm reading the excerpt below from Joe Albahari's excellent "C# 9 in a Nutshell" and am trying to understand what's being described here in bold. Is anyone able to explain the alternative approach in a way that I can understand better? This seems somewhat backward to me for some reason.
Alternatives to interface reimplementation
Even with explicit member implementation, interface reimplementation is problematic for a couple of reasons:
The subclass has no way to call the base class method.
The base class author might not anticipate that a method be reimplemented and might not allow for the potential consequences.
Reimplementation can be a good last resort when subclassing hasn’t been anticipated. A better option, however, is to design a base class such that reimplementation will never be required. There are two ways to achieve this:
When implicitly implementing a member, mark it virtual if appropriate.
When explicitly implementing a member, use the following pattern if you anticipate that subclasses might need to override any logic:
public class TextBox : IUndoable
{
void IUndoable.Undo() => Undo(); // Calls method below
protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}
public class RichTextBox : TextBox
{
protected override void Undo() => Console.WriteLine("RichTextBox.Undo");
}
If you don’t anticipate any subclassing, you can mark the class as sealed to preempt interface reimplementation.
The issue described, is that when a base class implements an interface, that base class may expect certain behaviour to occur.
The example of the textbox undo. Suppose that the base textbox does something important (or perhaps the actual work) for undoing.
Also for the sake of example, assumen that when writing the base class, the author did not think of inheriting classes (richtextbox here)
He could have written it as
public class TextBox : IUndoable
{
void IUndoable.Undo() => ....... undo logic here
}
Any inheriting class would not be able to call Undo directly (they would have to cast its base to IUndoable )
The problem now is, when other code, use the IUndo implementation (for example a menu item), the important undo in the base class would not be called, unless the inheriting class does this explicitely
Still the same with:
public class TextBox : IUndoable
{
public void Undo() => ...... undo logic here
}
The inheriting (RichTextBox) class, could call its base when explicitly implementing Undo, but it wouldn't be sure.
If RichTextBox makes its own Undo and hides the base Undo, there is no direct impulse to call the base Undo (Although more so than the first option)
In the end, what the base class author wants, is that when external code calls the IUndoable.Undo method, the required code is always called.
(Side note: In an abstract class that could be handled differently, but this is a directly usable class, that may or may not be inherited)
Making the implicit implementation virtual helps a bit:
public class TextBox : IUndoable
{
public virtual void Undo() => ...... undo logic here
}
As soon as an inheriting class overrides the method, the default snippet also calls the base class, but that is assuming the snippet is used, and base.Undo still is called, leaving the option to the inheritor.
That gives the last example as you included it:
public class TextBox : IUndoable
{
void IUndoable.Undo() => Undo(); // Calls method below
protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}
This gives a more secure option for inheriting classes to implement their own undo, without losing the undo of the base class (unless the inheriting class explicitly implements IUndoable as well, but let's not go there :P )
In the richtextbox example, the Undo is overriden, but the base Undo is not called. Exactly the sort of situation that could cause the base class implementation of 'undo' to be skipped.
But here, if something (a menu item for example) calls Undo of IUndoable the explicit implementation is called, forcing the required base class undo functionality to run, but also the overriden implementation of the inheriting class (richtextbox)
As I understood, what the author wants to say is that instead of hiding members of the base class, override them. Hiding is when child class has a member with the same signature, yet it's not marked virtual in the base class.
i.e. if ParentClass has method A(); If you want it to be overridden by ChildClass, make A() a virtual method. Or if you don't want A() to be overridden, introduce a protected method, that A() will use and make that protected method virtual for childs to override if needed.
Hope this answers your question.
Is anyone able to explain the alternative approach in a way that I can
understand better?
All it is saying is that if you try and do my below code it won't compile.
So then what are you to do if you need to use explicit interface implementation and an inheriting class needs to alter that behaviour? Well, you use the exact code you mentioned in your question. It allows you to use explicit interface implementation and allow it to be overriden.
That is it. That is all it is saying.
using System;
public interface IUndoable {
void Undo();
}
public class TextBox : IUndoable
{
void IUndoable.Undo() => Console.WriteLine ("TextBox.Undo");
}
public class RichTextBox : TextBox
{
void IUndoable.Undo() => Console.WriteLine ("RichTextBox.Undo");
}
public class Program
{
public static void Main()
{
}
}
Wait, before you start thinking, I would like to clear that I am NOT going to ask the routine differences between Interface and Abstract.
I had gone through the difference between Abstract and Interface in MSDN.
It is said :
By updating the base class, all inheriting classes are automatically updated with the change.
Interfaces, on the other hand, cannot be changed once created. If a new version of
an interface is required, you must create a whole new interface.
See this : -
Can anyone prove this using following example: -
abstract class WashingMachine
{
abstract public void Wash();
}
class Philips : WashingMachine
{
public Philips() { }
override public void Wash(){//Wash code here....}
}
class Samsung : WashingMachine
{
public Samsung() { }
override public void Wash(){//Wash code here....}
}
class Videocon : WashingMachine
{
public Videocon() { }
override public void Wash(){//Wash code here....}
}
Now, If I added following new abstract method in WashingMachine : -
abstract public void Rinse(int loadSize);
How all inheriting classes (i.e. Philips/Samsung/Videocon) will automatically get updated with the change?
They won't get updated - you still have to manually add an implementation of Rinse to each and every class that inherits from WashingMachine.
What I believe the MSDN says is that if you have a non-abstract method defined in an abstract class and you change that method, all classes that inherit from the abstract class will benefit from the change automatically.
Your concrete derived types all need to provide an implementation of any inherited abstract member...thus your types will still need to provide a Rinse implementation when you modified the base.
http://msdn.microsoft.com/en-us/library/sf985hc5(v=vs.71).aspx
This is a confusion programmers normally get when read difference between interface and abstract class. the line you refer is only true if the change in the abstract class is concrete. what i mean is you added a property or a method with implementation. Or if i am more specific, any change in base abstract class which does not make any concrete class abstract. Such change is possible in abstract classes and there is no way you can add such change in interface.
How all inheriting classes (i.e. Philips/Samsung/Videocon) will automatically get updated with the change?
They will suddenly become non-compileable, isn't that an update?
But I'd like to point out that there's in fact no difference between abstract method in abstract class and method in interface. Main difference lies in the fact that abstract classes can have methods with implementation and interfaces can not.
In fact, I'd say that I don't like MSDN definition and find it confusing and somewhat misleading.
A while back I wanted to create my own data mapper that would be much simpler than your average ORM. In doing so I found the need to have access to the type information of inheriting classes in my base class. My first thought was reflection, but it's too slow (if you use reflection though, check out Fasterflect as it 'almost' eliminates the performance problems of reflection).
So I turned to a solution that I later found out had it's own name: The Curiously Recurring Template Pattern. This mostly solved my problem, but learning how to correctly implement this pattern was a little challenging. The two main questions I had to solve were:
1) How can I let my consuming code work with my generic objects without needing to know the generic parameters the objects were created with?
2) How can I inherit static fields in C#?
The challenging part was actually figuring out the questions. Once I realized what I needed to do, solving these questions was pretty easy. If you find yourself in need of the CRTP, you will likely find yourself needing to answer these questions... they seem to go hand in hand.
Working with generics without knowing the generic parameter types
When using the CRTP it's good to have a non-generic base class (abstract if possible, but that's not too important) that your 'base' generic class inherits from. Then you can make abstract (or virtual) functions on your non-generic base class and allow consuming code to work with your objects without having to know the generic parameters. For example:
abstract class NonGenBase
{
public abstract void Foo();
}
class GenBase<T>: NonGenBase
{
public override void Foo()
{
// Do something
}
}
Now consuming code that has no knowledge of what T is supposed to be can still call the Foo() procedure on your objects by treating them as instances of the base class.
How to solve the static field inheritance problem
When using the CRTP to solve a problem, it's often beneficial to provide access to static fields in inheriting classes. The problem is that C# doesn't allow inheriting classes to have access to those static fields, except through the type name... which often seems to defeat the purpose in this situation. You may not be able to think of a clear example of what I'm talking about and explaining one is beyond the scope of this answer, but the solution is simple so just tuck it away in your knowledgebase and when you find a need for it you'll be glad it's there :)
class GenBase<T>: NonGenBase
{
static object _someResource;
protected object SomeResource { get { return _someResource; } }
}
This 'simulates' inheritance of static fields. Keep in mind, however, that static fields on a generic class are not scoped across all your generic implementations. Each generic implementation has its own instance of the static field. If you want a single static field that is available to all the implementations, then you simply need to add it to your non-generic base class.
How can I inherit static fields in C#?
I know it's been a long time since you asked this, but, note that in the .NET 6 Preview, you can put static abstract members on an interface. (IIRC, this feature won't be in the release for .NET 6, it will be in preview status until .NET 7).
So, you can do something like this:
public interface IBoundedCollection
{
public static abstract int MaximumItemCount { get; }
}
public abstract class BaseCollection
{
public abstract int Count { get; }
public abstract int GetMaximumItemCount();
public abstract BaseCollection CreateUntypedCopy();
}
public abstract class BoundedCollection<TDerived> : BaseCollection
where TDerived : BoundedCollection<TDerived>, IBoundedCollection
{
public override int GetMaximumItemCount() => TDerived.MaximumItemCount;
public abstract TDerived CreateTypedCopy();
public override BaseCollection CreateUntypedCopy()
=> CreateTypedCopy();
}
public class LimitTenCollection : BoundedCollection<LimitTenCollection>, IBoundedCollection
{
public static int MaximumItemCount => 10;
public override int Count { get; }
public override LimitTenCollection CreateTypedCopy() => new LimitTenCollection();
}
Note the following:
You can work with BaseCollection without working with type arguments. For example, you can use Count, GetMaximumItemCount(), and CreateUntypedCopy().
BoundedCollection<TDerived> can provide the implementation for MaximumItemCount since TDerived is constrained to IBoundedCollection
I don't know if this has to do with how FindControl works or how scope works. But my base class is having a hard time seeing the fields of child classes. Currently I'm planning have the derived class set a property in the base class, but there are a lot of derived classes, so that isn't a very attractive solution.
public class BasePage:Page
{
public void DoSomethingWithDerivedPageControl()
{
//foo is always null.
Control foo = FindControl("Foo");
}
}
public class DerivedPage : BasePage
{
//In real life, this is the code generated .aspx.designer.cs file.
protected Label Foo;
}
FindControl doesn't use fields - it uses the controls which have been added to the page, and checks their ids.
Presumably your control hasn't been added to the page at the time when DoSomethingWithDerivedPageControl is called.
It would be helpful if you could tell us what you're really trying to achieve... if all your derived types should have a control called Foo, why not just put it in the base class to start with?
public abstract class BasePage:Page
{
abstract protected Label Foo {get;}
public void DoSomethingWithDerivedPageControl()
{
Control foo = this.Foo;
}
}
public class DerivedPage : BasePage
{
override protected Label Foo { get; set;}
}
Now, I suspect that's not wholy fulfilling your need. But, a base class doesn't/cant' know about it's children. Your only option to find a random field in a child class, is to just ignore the fact that they are base/derived, and just use reflection of it, as if it were an unrelated class.
To answer your title question, inheritance runs from base class to derived class, not the other way. A member is either defined in a base class, and inherited by the derived class, or defined in the derived class and unknown to the base.
It stands to reason that a base class referring to a child member couldn't compile, since the base class definition has no knowledge of that member.
Whoa, this is scary that your even trying to do this. The base class shouldn't know anything about the derived class.
Can I somehow force a derived class to always call the overridden methods base?
public class BaseClass
{
public virtual void Update()
{
if(condition)
{
throw new Exception("..."); // Prevent derived method to be called
}
}
}
And then in a derived class :
public override void Update()
{
base.Update(); // Forced call
// Do any work
}
I've searched and found a suggestion to use a non-virtual Update() but also a protected virtual UpdateEx(). It just doesn't feel very neat, isn't there any better way?
I hope you get the question and I am sorry for any bad English.
Use the template method pattern - don't override the base method which needs to do some work, override one specific bit, which can either be abstract or a no-op in the base class. (The decision about whether to make it a no-op or abstract is usually fairly obvious - does the base class make sense on its own, as a concrete class?)
It sounds like this is basically the pattern you've found with UpdateEx - although it's usually UpdateImpl or something similar in my experience. There's nothing wrong with this as a pattern, in my view - it avoids any idea of forcing all derived classes to write the same code to call the base method.
This took me a bit to get what Update and UpdateEx would look like. Here's a code example that might help others.
public class BaseClass
{
// This is the Update that class instances will use, it's never overridden by a subclass
public void Update()
{
if(condition);
// etc... base class code that will always run
UpdateEx(); // ensure subclass Update() functionality is run
}
protected virtual void UpdateEx()
{
// does nothing unless sub-class overrides
}
}
A subclass will never have any implementation for Update(). It'll uses UpdateEx() to add implementation to Update();
public class ConcreteClass : BaseClass
{
protected override void UpdateEx()
{
// implementation to be added to the BaseClass Update();
}
}
Any instance of ConcreteClass will use the BaseClass implementation of Update() along with however ConcreteClass extends it with UpdateEx().
I think that the suggestion which you found is good.
The only base class method which you can't avoid calling from the subclass in base class constructor.
I think having a non-virtual base member that calls a virtual "hook" that can be extended is the most common solution for this kind of problem.
Depending on your use case, you might want to use an event instead, but the usual pattern for implementing an event is to have a virtual OnEvent method that subclasses can override instead of adding an event handler, so in your example case it boils down to the same thing.