Okay, the title may sound a bit confusing, just read my explanation here to understand what I mean:
I got a base class, lets call it BaseProvider. This class looks like this:
public abstract class BaseProvider
{
public abstract void NewItem(int type);
}
Now I add a second class that derives from the BaseProvider. Lets call it TestProvider:
public class TestProvider : BaseProvider
{
public override void NewItem(int type)
{
}
}
Okay, now here comes my question / problem:
As there are different sub-types that this provider should be able to handle, I created the parameter int type. However it would be much nicer to be able to use Enums. And as every data provider will have a different set of sub-types I can't reuse a already existing one.
Now my method signature has to match exactly the one from the base class which makes it impossible to change the parameter type to an enum (even though an enum is basically an int).
I did try to define my deriving class like the following:
public class TestProvider : BaseProvider
{
public override void NewItem(MyEnum type)
{
}
}
enum MyEnum : int
{
TEST = 1
}
As excpeted this does not work...
So my question now is:
Is it possible to overwrite a base function with a different parameter type that derives from the parameter type defined in the base class? If yes how?
No, absolutely not - and here's why... This code still has to work:
BaseProvider provider = new TestProvider();
provider.NewItem(10);
That's just the normal requirements of polymorphism. You can't change a signature when you're overriding, because callers may be considering your instance in terms of the base class instead. (Indeed, if they're not doing so, why bother having the abstract method at all?)
Now you can overload the method:
public override void NewItem(int type)
{
NewItem((MyEnum) type);
}
public void NewItem(MyEnum type)
{
...
}
That's not quite the same thing, but it probably achieves what you want.
Alternatively, you could make BaseProvider generic:
public abstract class BaseProvider<T>
{
public abstract void NewItem(T type);
}
public class TestProvider : BaseProvider<MyEnum>
{
public override void NewItem(MyEnum type)
{
}
}
You are actually missing out the concept of overriding here. It is not about changing method definition. It is about changing method behavior. What you could do here is either overload, or make sure you cast your enum as int before call.
Related
Okay, I have a small hiccup.
I want to implement an interface with a generic parameter type, and then extend that implementation with another parameter type, and not have to do the initialization all over again.
Basically, I have a similar structure to this:
interface IBase<MemberType>;
abstract class Base : IBase<OneMemberType> {
protected OneMemberType member;
public void init() {
member = new OneMemberType();
}
}
class Extended: Base, IBase<AnotherMemberType> {
}
I want class Extended to have a "member" property of the "AnotherMemberType" type.
AnotherMemberType and OneMemberType both implement the same interface.
Any ideas how i could do that, without explicitly defining it in the Extended class?
This is the actual interface.
interface ILayer<TextureProviderType>
{
Texture2D getTexture();
byte[,] getArray();
void generate();
}
Updated
I'm trying to have specific objects that extend the BaseLayer class and that each use a specific TextureProvider child, and only have to instantiate the texture providers in the base class.
Update 2
Okay, it has nothing to do with interfaces apparently. What I want to have is a generic base class member, that can be assigned a type in the extended children classes.
You can implement the interface methods just once and it will work for both interfaces.
If you want different implementations per interface, you must use explicit implementations or use the generic type parameter in the signature of your interface methods.
Point is, you can't have 2 methods with the same signature in your class and have the CLR know which one to use.
Edit: after reading you comment on the problem you're trying to solve:
Wouldn't a generic type parameter in your BaseLayer + inheritance in your TextureProviders work? Would look something like this:
class TextureProvider
{
public TextureProvider()
{
}
public void Foo()
{
}
}
class SpecialTextureProvider : TextureProvider
{
public SpecialTextureProvider()
: base()
{
}
}
class BaseLayer<TP> where TP : TextureProvider, new()
{
public BaseLayer()
{
var tp = new TP();
}
}
class SpecificLayer : BaseLayer<SpecialTextureProvider>
{
}
Alternatively, you could use the factory pattern.
Suppose I have a class like so:
public class MyClass<T> where T : BaseClass, new()
{
public Boolean DoWork()
{
// do the work, obviously.
}
}
And in some method I need to DoWork() on some MyClass<T> for which I don't need to know T. As far as I know, I need to refer to my MyClass<T> parameter and reiterate the constraints for T, like so:
public void DoLotsOfWork(MyClass<T> item) where T : BaseClass, new()
{
// do some work
// no need to know what T is here:
item.DoWork();
// maybe do some other work.
}
Can method DoLotsOfWork() refer to MyClass<T> without reiterating the constraints on T? (Or possibly even knowing about T?)
The way to handle this is to make DoLotsOfWork generic.
public void DoLotsOfWork<T>(MyClass<T> item) where T : BaseClass, new()
{
// do some work
// no need to know what T is here:
item.DoWork();
// maybe do some other work.
}
You cannot refer to a MyClass type, and access any information specific to that type, without providing any generic argument, no. (At least not using static typing; you'd need to move to things like reflection to do that.)
If you can alter the MyClass<T> class definition, then you can make it derive from a non-generic base class that specifies your method as abstract:
public abstract class MyClassBase
{
public abstract Boolean DoWork();
}
public class MyClass<T> : MyClassBase where T : BaseClass, new()
{
public override Boolean DoWork()
{
// do the work, obviously.
}
}
Then, use this base class as the parameter type:
public void DoLotsOfWork(MyClassBase item)
{
item.DoWork();
}
This approach is used in the .NET Framework, where Task<Result> derives from Task. The latter contains the members that do not rely on the generic type, such as Wait().
You could declare the parameter as dynamic:
public void DoLotsOfWork(dynamic item)
{
// do some work
// no need to know what T is here:
item.DoWork();
// maybe do some other work.
}
Makes your code prettier, but there is a performance hit. However, if you call DoLotsOfWork several times in the life of the app, you should only take a performance hit on the first call, so the cost should be negligible.
I would like to have an interface for a problem called IProblem. With two methods: Solve() and CheckArguments(). The Problem class will implement the CheckArguments() function because it will be the same for all the problems. But then I have different types of problems like EasyProblem and HardProblem that have different implementations of Solve() method but the CheckArguments() method always be the same and I always want to use the base class Problem()'s implementation.
I would like to have correct modifiers and I'm a bit confused on which method being defined in which class/interface. Not to mention I also have a test project for both these functions.
I'm not sure if your question is "what to use", but I'd suggest an interface and an abstract class:
public interface IProblem {
void Solve();
void CheckArguments();
}
public abstract class Problem : IProblem {
public abstract void Solve();
public void CheckArguments() {
...
}
}
public class EasyProblem : Problem
{
public override void Solve()
{
....
}
}
This way, check arguments is implemented in the base class, all derived classes implement IProblem and every derived class must implement Solve.
If you leave out the interface and only support classes which derive from Problem, you'll make sure that a given class can't give it's own implementation of CheckArguments().
public abstract class Problem {
public abstract void Solve();
public void CheckArguments() {
...
}
}
public class EasyProblem : Problem
{
public override void Solve()
{
....
}
}
...
static Main(string[] args)
{
List<Problem> problemsToSolve = ...
foreach(var problem in problemsToSolve)
{
problem.CheckArguments();
problem.Solve();
}
}
You can try something like:
public interface ISupportArguments
{
bool CheckArguments();
}
public abstract class AbstractProblem : ISupportArguments
{
public bool CheckArguments() {
return true;
}
public abstract void SolveProblem();
}
so every your class derives from AbstractProblem and override it's own version of
SolveProblem(..)
The class structure has been shown by Matten very well.
As regards access modifiers: I'd propose a defensive approach, so that you use the most restrictive access modifier that solves the problem. It is easier to be less restrictive afterwards than to be more restrictive as you might have to explain to some users of your code why they cannot use it anymore.
So for the types (interface and classes): if you don't need them in other assemblies, rather define them as internal. If you want to access the types from your test project, you can use the InternalsVisibleTo attribute to be able to access them from specific assemblies. You add the attribute to the assembly containing the types and provide the name (and for strong named assemblies some additional data) of the test assembly as a parameter.
The same applies to the members. You can also think about implementing the interface explicitly, so you can access the methods only if you access the class via the interface.
I've got an abstract class like this;
public abstract PropertyBase
{
public static System.Type GetMyType()
{
return !!!SOME MAGIC HERE!!!
}
}
I'd like to subclass it, and when I call the static GetMyType(), I'd like to return the subclass's type. So if I declare a subtype;
public class ConcreteProperty: PropertyBase {}
then when I call
var typeName = ConcreteProperty.GetMyType().Name;
I expect 'typeName' to be set to "ConcreteProperty." I suspect there's no way to do it, but I'm interested if anyone out there knows a way to get this info.
(The particular problem I'm trying to solve is the verbosity of dependency properties in WPF; I'd love to be able to do something like this;
class NamedObject : DependencyObject
{
// declare a name property as a type, not an instance.
private class NameProperty : PropertyBase<string, NamedObject> { }
// call static methods on the class to read the property
public string Name
{
get { return NameProperty.Get(this); }
set { NameProperty.Set(this, value); }
}
}
And I almost have an implementation, but I can't quite get the info I need out of my NameProperty class.)
You can partially achieve (1-level of inheritance deep) using generics:
class PropertyBase<T>
{
public static Type GetMyType() { return typeof (T); }
}
// the base class is actually a generic specialized by the derived class type
class ConcreteProperty : PropertyBase<ConcreteProperty> { /* more code here */ }
// t == typeof(ConcreteProperty)
var t = ConcreteProperty.GetMyType();
The subclassing bit will not work, because a static method is tied to a type. It is a method of a type, not a method of an instance. The subtype does not contain the static methods of a base type, because they are different types and the static method is tied to the base type. Even though the compiler might allow you to call a static method of a base class as through a derived class, it will in reality call the method from the base class. It's just syntax sugar. For the same reason you cannot "override" static methods in subclasses because it would make little sense.
Just wondering why would need to do something like this?
var typeName = ConcreteProperty.GetMyType().Name;
Anyhow you know the type while calling the method, you can simply do this as well..
var typeName = typeof(ConcreteProperty).Name;
Just in case you need to do this, you can use "shadowing" to override the implementation of base class in child class.
public class ConcreteProperty : PropertyBase {
public new static Type GetMyType {
//provide a new implementation here
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
I can do
public class MyGenericClass : DL
//but i cannot do
public class MyGenericClass <T> : T
How would i do the second? if i cannot do that, how can i do something like
public class MyGenericClass <T>
{
T obj;
//have all MyGenericClass.XYZ call obj.XYZ
}
This is not possible, because depending on what type T is, the public interface of MyGenericClass would change.
If you have lots of different classes that all expose the same interface, you could declare MyGenericClass to expose that interface, and in the implementation of all of the functions delegate the calls to obj
The specific question, why can't you do this:
public class MyGenericClass<T> : T
And you can do this:
public class MyGenericClass<T>
{
T obj;
}
The reason is that the CLR likes to be able to compile a single version of the code for MyGenericClass that will work for any reference type specified for T.
It can do this for the second case, because it can quietly replace T with object and insert appropriate casts, roughly equivalent to:
public class MyGenericClass
{
object obj;
}
But for the inheritance version, that trick doesn't work.
Also, many useful facilities would be impossible to describe through interface constraints. When you inherit from a type, you can do a lot more than just call methods on it - you can override them as well. Consider this hypothetical example:
class MyBase
{
public virtual void MyVirtual() { }
}
class MyGenericDerived<T> : T
{
public override void MyVirtual()
{
Console.WriteLine("Overridden!");
}
}
MyBase obj = new MyGenericDerived<MyBase>();
obj.MyVirtual();
What I want to do there is something like a "mix-in", where MyGenericDerived supplies definitions for virtual functions in whatever base it is applied to. But how does the compiler know that T will have a method called MyVirtual that can be overridden? I'd need to put a constraint on T. How would I express that through interfaces? It's impossible. Using interfaces to describe constraints isn't an adequate solution once you allow inheritance from type parameters. So that's another reason why it doesn't exist in the language today.
You could do something like
public interface IXyzable { void xyz(); }
public class MyGenericClass<T> : IXyzable where T : IXyzable {
T obj;
public void xyz() {
obj.xyz();
}
}
Edit: Now I understand the question
You'll need all your possible T's to implement some interface so that you know that obj.XYZ() makes sense, then you can do
public interface Ixyz
{
void XYZ();
}
public class MyGenericClass<T> : Ixyz where T:Ixyz, new()
{
T obj;
public MyGenericClass()
{
obj = new T();
}
public void XYZ()
{
obj.XYZ();
}
}
I've made MyGenericClass implement Ixyz too since it obviously does expose the right method, but maybe that's best left out since it allows
var x = new MyGenericClass<MyGenericClass<SomeClass>>();
which is unlikely to ever be a good idea.
This is pretty much duck-typing, but you could use reflection.
When you create the generic class with a reference to the obj, use reflection to try and find a method with the right signature. As long as you store a reference to the method, performance won't be too bad.
class BaseGeneric<T>
{
private T obj;
private MethodInfo mi;
private const string MethodNameOfInterest = "Xyz";
public BaseGeneric(T theObject)
{
this.obj = theObject;
Type t = obj.GetType();
mi = t.GetMethod(MethodNameOfInterest);
}
public void Xyz()
{
mi.Invoke(obj, null);
}
}
Of course, you would need to add a lot more for error checking and such, but that is the gist of what you could do. Also, don't forget to add the System.Reflection namespace to your using clause.
The .NET type system won't allow type declarations of the form you're attempting. One reason why this is disallowed should be intuitive: how would MyGenericClass<T> act when T is a sealed class (e.g. System.String)?
If you absolutely need this functionality (and you know that the type T you'll be using isn't sealed), you can generate proxies at runtime using the classes in the Reflection.Emit namespace. It may also be possible to achieve this effect using AOP tools like PostSharp.
What about this:
class BaseClass<T>
{
public T property { get; set; }
}
class GenericClass<T> : BaseClass<T>
{
}
class Program
{
static void Main(string[] args)
{
GenericClass<int> l = new GenericClass<int>();
l.property = 10;
}
}
This achieves what you want to do?