I have an abstract class ClassA, with an abstract method that takes a paramter of type ClassB. Several classes derive from it. Now I add another project, which has similar functionality, but needs a slightly different base ClassA, to derive its several classes from. The main difference: The new base class, ClassC, shouldn't ClassB as argument, but another one, that's derived from B, ClassD. ClassC should then be used as base by several classes again.
Is this possible? This is more of a question out of curiousity. I know it is possible with generics, by doing this:
public abstract void Method1<T>(T parameter) where T : ClassB;
...
public override void Method1<ClassB>(ClassB parameter) {
Is it possible without generics? And is there any dowside to them, aside from having to type the type twice?
abstract class ClassA
{
public abstract void Method1(ClassB parameter);
}
class DerivingClasses1 : ClassA
{
public override void Method1(ClassB parameter)
{
// do something
}
}
// -------
abstract class ClassC : ClassA
{
// This would have to override Method1 of ClassA somehow,
// instead of overloading it.
public abstract void Method1(ClassD parameter);
}
class DerivingClasses2 : ClassA
{
public override void Method1(ClassD parameter)
{
// do something
}
}
// -------
class ClassB
{
}
class ClassD : ClassB
{
}
In my opinion, the best approach would be to override the base class method with a sealed implementation that invokes the overload with the new parameter type, thereby insulating the user from the type conversion.
abstract class ClassC : ClassA
{
public override sealed void Method1(ClassB parameter)
{
this.Method1(parameter as ClassD);
}
public abstract void Method1(ClassD parameter);
}
Edit: If used in production, you should perform proper type checking in order to avoid getting unexpected nulls:
abstract class ClassC : ClassA
{
public override sealed void Method1(ClassB parameter)
{
if (!(parameter is ClassD))
throw new ArgumentException(
"Parameter must be of type ClassD.", "parameter");
this.Method1((ClassD)parameter);
}
public abstract void Method1(ClassD parameter);
}
Just implement both methords in ClassC.
Override abstract method with another one, having different parameters
This is not really possible, however you could use a common interface:
interface IMyType {}
class MyTypeBase
{
public abstract void Method1(IMyType parameter);
}
Related
See the code below.
In the base handler (MyBaseHandler) I have a handler of all objects of MyBaseClass.
Then I have a subclass handler (HandlerA) where I want to handle the objects of class ClassA.
So I want to override the base handler for class ClassA; all other classes should have the base handling.
But this does not work as expected. The base Handle(MyBaseClass) is called for all the objects, including objA where I want to use Handle(ClassA).
I would like this generic handing so I can easily extend with other handling for other classes as needed. This code compiles. If I add the "override" keyword to the Handle in HandlerA it will not compile.
How can achieve what I want with the simplest code? Is it possible to achieve this without a lot of code to check the type of the class? Is it possible to use generics to achieve this?
abstract class MyBaseClass {}
class ClassA : MyBaseClass {}
class ClassB : MyBaseClass {}
class ClassC : MyBaseClass {}
class ClassD : MyBaseClass {}
abstract class MyBaseHandler
{
public void Go()
{
ClassA objA = new ClassA();
Handle(objA);
ClassB objB = new ClassB();
Handle(objB);
ClassC objC = new ClassC();
Handle(objC);
ClassD objD = new ClassD();
Handle(objD);
}
public virtual void Handle(MyBaseClass obj)
{
...
}
}
public class HandlerA : MyBaseHandler
{
public void Handle(ClassA obj)
{
// This code does not get called.
...
}
public void Run()
{
Go();
}
}
MyBaseHandler only knows about Handle(MyBaseClass obj). It doesn't matter that Handle has the same name as a method in MyBaseHandler, or even that the signatures are compatible. If you were to override Go in HandlerA, your code would work as expected, but as it is, MyBaseHandler can never resolve to a method defined in a sub-class.
You are on the right track making the method virtual in MyBaseHandler, but you need to follow through and create an override in HandlerA:
class HandlerA : MyBaseHandler
{
public override void Handle(MyBaseClass obj)
{
if (obj is ClassA)
{
Handle(obj);
return;
}
base.Handle(obj);
}
public void Handle(ClassA obj)
{
// This code gets called by override void Handle(MyBaseClass obj)
}
// ...
}
Since Handle(MyBaseClass obj) matches the signature of the base class, you are able to override and MyBaseHandler can "see" the method. You can then check if obj is an instance of ClassA and go from there.
This is not going to work, because compiler expects method with signature indicating MyBaseClass as argument. If you want to override it, the signature should be the same, so in HandlerA it should be override void Handle(MyBaseClass obj). ClassA inherits from MyBaseClass, so it will still take it as argument. You can then cast it inside function if you need it to be ClassA.
public override void Handle(MyBaseClass obj)
{
ClassA objA = obj as ClassA;
if(objA == null)
{
throw new ArgumentNullException("Argument to this handler should be ClassA") ;
}
// your code
}
I have a generic type G<T> where T : A, where A is an abstract class. In each class B derived from A I want to have a field of type G<B>, without writing repetetive code, however I'm not sure if it's even possible. One way to do this would be
abstract class A
{
protected object g;
protected abstract void SetG();
public A()
{
SetG();
}
}
class B : A
{
protected override void SetG()
{
this.g = new G<B>();
}
public B() : base() {}
}
But this would mean a lot of repetetive code in every derived class. Is there a better way to do this?
You could add an extra abstract class in between:
public abstract class A<T> : A where T : A
{
protected override void SetG()
{
this.g = new G<T>();
}
}
...then, update your B declaration to:
public class B : A<B>
{
public B() : base() { }
}
I believe that what you are trying to do is a Covariant Conversion. See this MSDN article on using delegates and see if that works for you. Look in the section "Using Delegates with Covariant Type Parameters".
In your A:, create a delegate:
Func<G<A>> GetG;
Then, in your derived classes, set this func pointer to a function of type
Func<G<B>>
Bingo!
I've got an issue with generics. I've those classes :
abstract class BaseTestClass<T> : where T : class, new()
{
//base test class implementation
public abstract void Run(BaseDataClass<T> data);
}
class BaseDataClass<T> : where T : class, new()
{
//base data class implementation
}
class DataA : BaseDataClass<SettingsA>
{
//some stuff
}
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
//Doesn't Work!
public override void Run(DataA data)
{
}
}
My question if why can't I use the inherited class in the abstract method ?
[EDIT]
The error at compilation is:
TestA does not implement inherited abstract member Run(BaseDataClass)
You can, but the BaseTestClass<SettingsA> base class simply does NOT have a method to override of the signature Run(DataA), but only one of the signature Run(BaseDataClass<DataA>).
The generic inheritance also means that the generic T type is the same.
You can implement this with an additional generic argument, Type-Safe and without cast:
internal abstract class BaseTestClass<T, Y>
where T : class, new()
where Y : BaseDataClass<T>
{
private T m_data;
//base test class implementation
public abstract void Run(Y data);
}
public class BaseDataClass<T> where T : class, new()
{
}
internal class TestA : BaseTestClass<SettingsA, DataA>
{
public override void Run(DataA data)
{
throw new NotImplementedException();
}
}
class DataA : BaseDataClass<SettingsA>
{
}
class SettingsA
{
}
This is type-safe because the constraint is
where Y : BaseDataClass<T>
If you don't need T directly in you base class, you can only use one generic parameter and remove T
Your second method does not compile because there is no method to be overriden by it, removing the override modificator will make your code compile.
If you want to have a method which will run only when the parameter is of type DataA, but still execute the interface method implementation, you can do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
}
public void Run(DataA data)
{
//dp some stuff
Run((BaseDataClass<SettingsA>)data);
}
}
But note that this is not bullet proof, you could miss boxed calls, the better way is do this way:
class TestA : BaseTestClass<SettingsA>
{
//Works!
public override void Run(BaseDataClass<SettingsA> data)
{
var myDataA = data as DataA;
if (myDataA != null)
{
//your parameter is a DataA;
}
}
}
It does not work because you cannot override one method with two methods. Take the override off of one of the methods in TestA, and it will all work. There's no point in overriding a single method twice, anyhow, within a single class.
public abstract class A
{
public abstract void Process();
}
public abstract class B : A
{
public abstract override void Process();
}
public class C : B
{
public override void Process()
{
Console.WriteLine("abc");
}
}
This code throws an Compilation Error: 'B' does not implement inherited abstract member 'A.Process()'.
Is there any way to do this?
Just leave out the method completely in class B. B inherits it anyway from A, and since B itself is abstract, you do not explicitly need to implement it again.
Works for me in VS2008; no errors, no warnings. BUT, there's no reason to have the 'override' in B. This code is equivalent:
public abstract class A
{
public abstract void Process();
}
public abstract class B : A
{
}
public class C : B
{
public override void Process()
{
Console.WriteLine("abc");
}
}
The place where I've seen this sometimes is overriding a non-abstract virtual method with an abstract method. For example:
public abstract class SomeBaseType
{
/* Override the ToString method inherited from Object with an abstract
* method. Non-abstract types derived from SomeBaseType will have to provide
* their own implementation of ToString() to override Object.ToString().
*/
public abstract override string ToString();
}
public class SomeType : SomeBaseType
{
public override string ToString()
{
return "This type *must* implement an override of ToString()";
}
}
Alon -
This makes no sense. First of all, this does actually compile fine. Secondly, the abstract method you declared in A is inherited (still abstract) into B. Therefore, you have no need to declare Process() in class B.
--
Mark
Consider the following example. I have an interface MyInterface, and then two abstract classes MyAbstractClass1 and MyAbstractClass2. MyAbstractClass1 implements MyInterface, but MyAbstractClass2 does not.
Now I have three concrete classes.
MyConcreteClass1 is derived from MyAbstractClass1 but does not implement MyInterface.
MyConcreteClass2 is derived from MyAbstractClass2, but does implement MyInterface.
MyConcreteClass3 is derived from MyAbstractClass1, and does implement MyInterface.
Does ConcreteClass1 also implicitly implement MyInterface because it derives from MyAbstractClass1? Assuming MyAbstractClass1 implements the methods of MyInteface implicitly then ConcreteClass1 should not have to be cast to a MyInterface to access the MyInteface methods right?
MyAbstractClass1 can implicitly implement a method of MyInterface as an abstract method, but can't explicitly implement a method of MyInterface as an abstract method. Why is this?
Is MyConcreteClass3 excessive because it's implementing an interface that is already implemented by its base class? Would there be a reason you would want to do that even if you knew all classes that derive from MyAbstractClass1 should also implement MyInterface.
Here's a class diagram
alt text http://files.getdropbox.com/u/113068/abstractclassesandinterfaces.png
Here's the code:
//interface
public interface MyInterface
{
void MyMethodA();
void MyMethodB();
void MyMethodC();
}
//abstract classes
public abstract class MyAbstractClass1 : MyInterface
{
public void MyMethodA()
{
}
void MyInterface.MyMethodB()
{
}
//Error: "the modifier abstract is not valid for this item"
//abstract void MyInterface.MyMethodC();
//This works
public abstract void MyMethodC();
public abstract void MyMethodZ();
}
public abstract class MyAbstractClass2
{
public void MyMethodX()
{
}
public abstract void MyMethodY();
}
//Concrete classes
//ConcreteClass 1: Only Abstract class implements the interface
public class ConcreteClass1 : MyAbstractClass1
{
public override void MyMethodC()
{
}
public override void MyMethodZ()
{
}
}
//ConcreteClass 1: Only Concrete class implements the interface
public class ConcreteClass2 : MyAbstractClass2, MyInterface
{
public override void MyMethodY()
{
}
public void MyMethodA()
{
}
public void MyMethodB()
{
}
public void MyMethodC()
{
}
}
//ConcreteClass 1: Both concrete and abstract class implement the interface
public class ConcreteClass3 : MyAbstractClass1, MyInterface
{
public override void MyMethodC()
{
}
public override void MyMethodZ()
{
}
}
Does ConcreteClass1 also implicitly implement MyInterface because it derives from MyAbstractClass1?
Yes.
ConcreteClass1 should not have to be cast to a MyInterface to access the MyInteface methods right?
Correct. (myConcreteClass1 is MyInterface) will evaluate true.
MyAbstractClass1 can implicitly implement a method of MyInterface as an abstract method, but can't explicitly implement a method of MyInterface as an abstract method.
Explicit implementation is to distinguish between overlapping member signatures. The explicit implementation is private to the class you are implementing it on, so it is not accessible to derived classes (and thus cannot be abstract). You also cannot force classes which derive from MyAbstractClass1 to explicitly implement MyInterface, so there is no way to ensure the abstract member will ever be implemented.
Is MyConcreteClass3 excessive because it's implementing an interface that is already implemented by its base class? Would there be a reason you would want to do that even if you knew all classes that derive from MyAbstractClass1 should also implement MyInterface.
Not necessarily, If you need to explicitly implement a member of the interface to distinguish it from an overlapping member on MyConcreteClass3. Otherwise it is unnecessary.
In this case, all three classes implement the interface (directly or indirectly). This is because MyAbstractClass1 implements MyInterface, and since MyConcreteClass1 derives from MyAbstractClass1, it also follows that you can treat MyConcreteClass1 as a MyInterface. MyConcreteClass2 can be treated with something that derives from MyAbstractClass1, as long as you treat it as a MyInterface. the derivation from MyInterface in ConcreteClass3 is a bit redundant since MyAbstractClass1 already implements MyInterface.
With all of that information, i'd say that yes, it is redundant to implement MyInterface on MyConcreteClass3 since it derives from MyAbstractClass1 which already implements MyInterface.
I think the reason that you cant have an abstract implementation of an interface method is that it provides no code itself and you cannot guarantee that it will be overriden in subcalsses. Use Virtual instead.
It's not redundant. Consider this class setup to simplify ...
public interface I
{
void A();
}
public abstract class B : I
{
public void A( )
{
Console.WriteLine("Base");
}
}
public class D : B
{
public void A()
{
Console.WriteLine("Hide");
}
}
public class U
{
public void M(I i)
{
Console.WriteLine("M!");
}
}
Executing this ...
var d = new D();
var i = (I)d;
var u = new U();
i.A();
d.A();
u.M(d);
u.M(i);
You will get ...
Base
Hide
M!
M!
If you add the interface from the derived class ...
public class D : B, I
{
public void A()
{
Console.WriteLine("Hide");
}
}
You will get ...
Hide
Hide
M!
M!
So, it effects which implementation of the interface method you get when you get the Iness of your derived class.