Say I have a bunch of code for all controls, yet I need subclasses that interact with my software suite to use those common methods. I really want my subclass to derive from the control, not the class with the common code. (A MyEdit should derive from Edit, not from MyControl). Also, the suite interacts with controls using an interface which MyControl derives from. In order to do this in C++, I would use multi-inheritance like so
class MyEdit : public Edit, public MyControl;
class MyControl : public IControl;
However, I suddenly discover that I shouldn't use multi-inheritance if I want some controls to be C# which doesn't support multi-inhertiance.
So I thought I could do this...
class MyEdit : public MyControl<Edit>;
template class MyControl<Type> : public IControl;
Convert the common control stuff into a template, and give it the type of control I want to derive from.
However I'm not sure this will work, because the template templatizes Edit, but it doesn't necessarily create one does it? When I create the template will I actually be able to create the Edit?
And secondly, if this is possible, is it possible in C#? What would it look like?
I can't say I quite followed your question, but in regards to:
However I'm not sure this will work,
because the template templatizes Edit,
but it doesn't necessarily create one
does it? When I create the template
will I actually be able to create the
Edit?
I would go for
template<class Controlled_t>
class MyControl : public Controlled_t, public IControl
{
//My Control inherits from its templated class
}
so that
MyControl<Edit> inherits Edit (which is created) and the interface
In C#, a class can only inherit from one other class, but it can implement multiple Interfaces, so if you want a class that can override behavior for more than one polymorphic type at runtime, you have to use Interfaces. The drawback of Interfaces is that they have no properties or base method implementations, so you may have to duplicate some of the methods in classes that implement the same Interface.
Another, C#-y way to get polymorphic runtime behavior is by attaching delegates. A lot of times I've found that what looks like a multiple-inheritance situation is better expressed as a multicast-delegate situation.
Related
I'm working on a project with the following (very simplified) structure:
BaseClass
SubClassA : BaseClass
SubClassB : BaseClass
There is a UI (with a lot of logic) which uses SubClassA, and then saves it to another component which takes BaseClass as a parameter but immediately casts the argument to SubClassB. This fails as the UI is passing in SubClassA.
UI:
MyComponent.Save(subClassA)
Component:
Save(BaseClass baseClass)
{
SubClassB subClassB = (SubClassB)baseClass;
...
the current implementation creates an instance of SubClassB in the UI and pass that across - but it leads to lots of code such as
SubClassB.Property1 = SubClassA.Property1a
I'm contemplating creating a common interface which the 2 sub classes would implement. It would be a lot of work but slowly I think I could flatten the current very deep hierarchy. Reworking either the UI or the component to use the other sub type would be just as much work as the structures are different (though many fields map). Is the interface approach the right way to go? I feel there might be something I'm missing.
If SubclassA and SubclassB are related only by their ability to Save, then yes, BaseClass would be better as an interface that both sub-classes implement.
It won't solve your immediate problem straight away: the component casting from base class to (the wrong) derived class. It looks like there could be several levels of refactoring to do here. Patching up the code so that the component casting to a SubclassA by making one for it to use is wasteful, I think. Changing the component so it can operate on a single common type would be a big win there.
Flattening a deep hierarchy would bring lots of other benefits, too - like making it simpler. If there end up being a few interfaces that they all implement, that's not necessarily a bad thing. Beware of lots of interface types hunting in packs, however.
In short, reworking both the UI and the component - and any other code, too - to work in terms of just a small number of interfaces, with no knowledge of the implementing classes, will pay dividends.
From a consumer standpoint, interfaces can do almost everything that abstract classes can do (the main exceptions being that a class can expose a field as a byref, while interfaces have no means of doing so, and that static members associated with a class can be grouped under the class name, static members related to an interface must be grouped under a different name). Except in those rare cases where it's necessary to expose a field as a byref, the primary advantage of an abstract class comes on the side of the implementation. All of the functionality associated with an interface must be provided separately in every class which implements it, even when such functionality is common to 99% of the classes which implement it. By contrast, if 99% of the concrete classes derived from an abstract class will implement a particular method the same way, it's possible for the abstract class to define that method once and let derived classes inherit it without having to pay it any heed whatsoever. Such an advantage can be nice, but there's a major catch: a class can only inherit functionality from one other class. Since interfaces don't include any functionality, they can be inherited from any number of other classes.
When one is defining an abstract class, I would suggest that one should in many cases also define an interface which includes the same public functionality (which the abstract class should implement), and avoid using variables or parameters of the abstract class type. This will allow implementations which can inherit from the abstract class to achieve the ease-of-implementation benefits that would come from doing so, but will also make it possible to define implementations which inherit from something else. Writing an implementation which inherits from some other type would be more work, but if code never uses the abstract-class type in variable, field, or parameter declarations, code which uses derivatives of the abstract class would work just as well with interface implementations that don't.
Why not make a Save() virtual within the base class - it seems like a better option. That way, if you have any common save functionality, you can use it and also give it other forms in derived classes - known as polymorphism.
class BaseClass
{
public virtual void Save()
{
//Use this keyword
}
}
class B : BaseClass
{
public override void Save()
{
base.Save();
}
}
I want to create a control MessageProvider just like ErrorProvider..what I did is, created a class and inherited from ErrorProvider..
But now problem is, instead of SetError and GetError methods, I want to have SetMessage and GetMessage..and those SetError and GetError methods should not be part of MessageProvider class..
How can I create a new control MessageProvider?
You cannot hide public methods from an inherited class as there is no private inheritance in the CTS. You can, however, easily add the SetMessage() and GetMessage() methods to your derived class and implement the desired functionality.
Your other option is to roll your own MessageProvider class that implements (mimics) only the desired functionality of ErrorProvider. This is probably more trouble than it's worth. I'd just derive and live with all the inherited functionality.
You could encapsulate the ErrorProvider within your new control.
I have several controls that all inherit from UserControl, and I have a MergeSort method that runs on UserControl types (to save me from writing out 6 different methods), but when I cast back to my custom controls after the sorting, it throws an error, what am I doing wrong? The mergesort method requires the Left property, which each custom control uses, so is there any other way I can do this?
MergeSort method looks like:
public UserControl[] MergeSort(UserControl[] array)
Cast looks like:
(CustomControl[])MergeSort(customControlArray);
I think you have to cast each of them manually:
CustomControl[] customControlArray;
...
UserControl[] sortedControls = MergeSort(customControlArray);
CustomControl[] sortedCustomControls = Array.ConvertAll<UserControl, CustomControl>(sortedControls, delegate(UserControl control)
{
return (CustomControl)control;
});
If you have .NET 3.5+ at your disposal you can use much "cooler" syntax. :)
Edit: the cooler syntax is:
UserControl[] sortedControls = customControlArray.ToList().ConvertAll(c => (CustomControl)c).ToArray();
:-)
(I deleted my previous answer because I think it was actually incorrect.)
It sounds like you need an abstraction between your controls and UserControl which represents common functionality. There are two main ways to accomplish this, and whichever one you use is a matter of personal coding preferences, how you plan to extend these further, how you organize your code in the project, etc...
Inherit from a base class. Basically, create a MyCustomControl (or whatever you want to name it) class which implements the common functionality between your custom controls. This would inherit from UserControl and your controls would inherit from this. Then your method would expect/return an array of this base class.
Implement an interface. You could create an ICustomControl (or whatever you want to name it) interface which represents the common functionality between your custom controls. Then your controls would inherit from UserControl as well as implement ICustomControl. Then your method would expect/return an array of this interface type.
I personally prefer the interface approach. Inheritance tends to be overused in a lot of people's object oriented code, and really shouldn't be. An interface better represents an abstraction (or code contract) as a type (as opposed to a class). But that's a much bigger discussion debate for another time, I suppose :)
In a namespace, is it possible to provide an alias for a class? And if not, why not?
By example, if I had several libraries of things that were derived from a contained, but named base class, but wanted to alias that as "BaseClass", while retaining its actual class name (i.e. "HtmlControl").
Then consumers could always come along and extend from HtmlControls.BaseClass, without having to figure out which class it really comes from.
using SomeClass = Large.Namespace.Other.FunkyClass;
class Foo : SomeClass
{
}
There really isn't an ideal way to do this in C#/.NET. What you can do is have a public BaseClass that inherits from an internal class. You can change this inheritance internally without breaking your consumers as long as the interface to the class remains intact.
public class PublicBaseClass : SomeInternalClass {
}
Consumers inherit from PublicBaseClass, and as long as you are careful, you can change what SomeInternalClass is as you wish.
You could create a dummy class that just inherits HtmlControl without adding any other functionality:
public class BaseClass : HtmlControl {}
The closest I know of is to customize your using statement:
using BaseClass = HtmlControls.BaseClass;
This is normally used to avoid ambiguity between classes with the same name in different used namespaces, without having to fully qualify one or the other. Your devs would have to include it in every code file, so probably not a good solution for what you're doing.
As far as deriving from BaseClass without knowing what you are actually deriving from, not possible. The compiler must, at some level, know what and where the parent class is, meaning it must be statically defined somewhere in code.
I have a .net-app that provides a mechanism to extend the app with plugins. Each plugin must implement a plugin-interface and must provide furthermore a constructor that receives one parameter (a resource context).
During the instantiation of the plugin-class I look via reflection, if the needed constructor exists and if yes, I instantiate the class (via Reflection). If the constructor does not exists, I throw an exception that says that the plugin not could be created, because the desired constructor is not available.
My question is, if there is a way to declare the signature of a constructor in the plugin-interface so that everyone that implements the plugin-interface must also provide a constructor with the desired signature. This would ease the creation of plugins.
I don’t think that such a possibility exists because I think such a feature falls not in the main purpose for what interfaces were designed for but perhaps someone knows a statement that does this, something like:
public interface IPlugin {
ctor(IResourceContext resourceContext);
int AnotherPluginFunction();
}
I want to add that I don't want to change the constructor to be parameterless and then set the resource-context through a property, because this will make the creation of plugins much more complicated. The persons that write plugins are not persons with deep programming experience. The plugins are used to calculate statistical data that will be visualized by the app.
Thanks for all the answers.
I’ve decided, that I let it be an interface because I don’t like to force the plugin-programmers to inherit from an abstract class so that he or she loses the possibility to inherit from an own base-class. Furthermore, deriving from an abstract class does not ensure that the plugin programmer really provides the needed constructor. It makes it only more probable (The programmer has still the possibility to add only one constructor that contains the desired parameter but that also has additional parameters, and that’s also bad. See the comments to the answer of Ken Browning).
Although I mentioned in my post that I don’t want such a property, I marked the answer of Danny Varod as accepted because I think in my situation it’s the most appropriate solution. Thanks to all who answered.
Plug-in extendability is a favorite of mine...
What I do is make sure the plug-in either implements the interface or inherits the base class of the appropriate "plugin socket".
In some places base classes are more appropriate (if the plug-in is a kind of X),
in some interfaces are more appropriate (if the plug-in does IX).
I do not pass the context to the construct, instead I use a property for that and a parameterless public constructor.
This also enables easier deserialization of plug-ins using reflection.
Interfaces cannot declare constructors. You might consider using an abstract class instead.
No, this does not exist. You are probably looking for an abstract class here.
Alternatively, you might try using a factory: make the constructor signature a method signature of another type:
public abstract class PluginFactory
{
public abstract IPlugin Create(IResourceContext context);
}
and then something like (and I always mess up this part if I want it to be short, hence the edit):
public class PluginContainer
{
public IPlugin LoadPlugin<T>(IResourceContext context) where T: PluginFactory, new()
{
var factory = new T();
return factory.Create(context);
}
}
Unfortunately, interfaces in C# can only contain methods, properties, events or indexers.
You could use and abstract class that all plugins would inherit from. You'd be able to force them to implement the constructor signature in that case.
The interface can't declare / enforce a constructor.
Define the interface and create an abstract base class that provides the most likely implementation of the constructor -- probably just saving the resource context passed in.
Encourage, but don't require, plugin authors to derive from the base class. There may be other useful methods that the base class could also provide.
Continue to use reflection to check the plugins.
As others have alluded to, using an abstract class to take care of the plumbing details is a common pattern for what you're trying to accomplish. Here is one design that avoids the need for a constructor with special parameters if the consumer inherits from the abstract base class Plugin:
public interface IPlugin
{
void Initialize(IResourceContext context);
//Other methods...
}
public abstract class Plugin : IPlugin
{
protected IResourceContext Context { get; private set; }
void IPlugin.Initialize(IResourceContext context)
{
Context = context;
}
//Abstract declaration of other methods...
}
Your code has to call Initialize behind the scenes after creating the Plugin, but this detail is hidden from typical users, as they generally don't have to implement IPlugin directly. Your typical user can just define a Plugin descendant and work with the Context property.
You might also want to look into various dependency injection frameworks (such as Ninject), though they're probably overkill for what you're doing. Still, looking at how they work may give you some ideas on different ways dependency injection can be managed.