I have a class M and many derived classes A:M, B:M, C:M
The derived classes A,B,C are obviously different, else they were not been declared.
M implements a member that needs to know the type of the calling class.
So, today I'm using an abstract member in M and individually override in each dervied class.
In M:
public abstract Do() {};
In A:
public override void Do()
{
DoMore<A>();
}
In B:
public override void Do()
{
DoMore<B>();
}
In C:
public override void Do()
{
DoMore<C>();
}
Is there a way to implement Do() in M just once for all derived classes ? Something like:
In M:
public Do<T>() {
DoMore<T>();
}
This does not work because DoMore() is casting on the derived class.
If you make the base class generic, you can make it "aware" of its derived type:
public class M<T>
{
public Do<T>()
{
DoMore<T>();
}
}
public class A : M<A> {...}
public class B : M<B> {...}
public class C : M<C> {...}
It will be possible in case you create the
DoMore method in the base class and make it abstract and override
in the child class so that appropriate method is called
but more or less it will be the
same as overriding Do method which you have just move to parent class and made it non abstract.
Related
This question already has an answer here:
Can we declare sealed method in a class
(1 answer)
Closed 4 years ago.
Code Snippet 1 (Compilation Error) - A.M2() cannot be sealed because it is not an override
abstract class A
{
public abstract void M1();
public sealed void M2()
{
// Do Something
}
}
Code Snippet 2 (Works Fine)
abstract class A
{
public abstract void M1();
public virtual void M2()
{
}
}
class B : A
{
public sealed override void M1()
{
}
public sealed override void M2()
{
}
}
Question - If I am providing the implementation of a method in the Abstract class itself, why would C# not allow me to mark it Sealed, why would it want me to override in the sub class, there after mark it as sealed. I cannot understand this discrepancy
Sealed keyword can only be put on functions that are overridable.
That function you specified, is not declared as a virtual function, and hence is not overridable. Also it does not make any sense for a function to be declared "virtual" and "sealed" as sealed cancels out being "virtual"
Sealed only can be used hand in hand with the "override" keyword, and stops other classes from overriding the functions themselves.
It has nothing to do with an abstract class. You cannot make a method as sealed in any class until it is an override method in derived class.
If you had intentions for restricting it from override in derived class then you better use private access modifier.
And the reason why you could use sealed in derived class; I've an example of it below
You have three classes A,B,C where B overrides A and C derives from B -> B:A, C:B
abstract class A
{
public abstract void MyMethod();
}
class B : A
{
public sealed override void MyMethod()
{
}
}
class C : B
{
public override void MyMethod()
{
}
}
In above example we could override method of A in B class because it is not sealed. But if you override method of B in class C then it is not allowed due to sealed keyword.
It will restrict further overrides from class B. Thats where we can use sealed
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 am working on a small project and I came across that problem.
The project output is a library containing an interface. I would like to implement that interface and seal the functions in it like this if possible:
public interface ITest
{
void SomeMethod();
}
class A : ITest
{
public sealed override SomeMethod()
{
}
}
The idea is to have the interface available to everyone and have some specialized class that implements it. The exception is that I want to make sure that if someone create a specialized class of type A, he/she won't be able to change the method's behavior.
The problem is you can't put the "override" keyword in there since the method isn't declared as "virtual" in the interface. And you can't declare it as "virtual" in the interface since it's not allowed. And you can't remove the "override" keyword since it's needed by "sealed".
Any workaround or brainstorming idea would be welcome, but if someone can come up with a solution that includes an interface, I'd be really happy to learn it!
Thanks!
EDIT: Forget this question! Like Ani said, I forgot that by default method in C# are sealed. Seems like it's always good to go back to the basics once in a while...
I may have completely misunderstood the question, but if your intention is to seal the method in A, you can just do:
class A : ITest
{
public void SomeMethod() { ... }
}
Unlike Java, methods in C# are sealed by default. Subclasses of A won't be able to override the method since it hasn't been marked virtual.
On the other hand, if your intention is to mark the method 'almost sealed' in the interface, so that it forces upon an implementing class to immediately seal it, that isn't possible. It isn't (and shouldn't be) the business of the interface to dictate such details of implementation - an interface is meant to represent a specification.
Use an abstract base class with internal visibility. This base class is not visible outside of the library but allows you to seal the method and the class still implements the interface.
public interface ITest
{
void SomeMethod();
}
internal abstract class SuperA : ITest
{
public abstract void SomeMethod();
}
class A : SuperA
{
public sealed override void SomeMethod()
{
}
}
Your understanding of sealed keyword is incorrect. As a method modifier, sealed is used to prevent a virtual method(defined in the base class) to be override in the next generation of derived classes. For example:
class Base
{
public virtual void M() { }
}
class Derived : Base
{
public sealed override void M() { }
}
class A : Derived
{
public override void M() { } //compile error, M is sealed in Derived
}
Developers can always use new modifier to define a method with the same name in the derived class, that hides the one defined in the base class.
if someone create a specialized class
of type A, he/she won't be able to
change the method's behavior.
If "specialized class" means a class derived from A, the answer is: he can always hide the method in A, but he can't change the method's behavior.
Why not use an abstract class like below.
Haven't tested it but this should work?
public abstract class Test
{
public virtual void SomeMethod() {}
//OR
public abstract void SomeMethod();//MSDN says:
//an abstract method is implicitly virtual
}
class A : Test
{
public sealed override SomeMethod()
{
}
}
Methods in C# are sealed by default.. Here is a sample
class Program
{
static void Main(string[] args)
{
A obj = new A();
obj.SomeMethod();
b ss = new b();
ss.SomeMethod();
Console.ReadLine();
}
}
public interface ITest { void SomeMethod(); }
class A : ITest { public void SomeMethod() {
Console.WriteLine("SomeMethod Called from Class A object");
} }
class b : A
{
//public override void SomeMethod()
//{
// Console.WriteLine("Called from Class B Object");
//}
}
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.