We have the following code:
public class A
{
protected virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
protected override void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
}
}
How to call Method() from class A in Some() method from class C?
We will assume that A and B are classes from the library and we can not change them.
Solution: https://stackoverflow.com/a/438952/8081796
B overrides Method() and A its marked as virtual and protected, the only way to call it (in its current format) is if B calls it somehow
public class B : A
{
protected override void Method()
{
base.Method();
Console.Write("B");
}
}
Or derived from A directly
public class C : A
{
public void Some()
{
Method();
}
}
virtual (C# Reference) | Microsoft Docs
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class. For example, this method can be overridden by any class that
inherits it:
Furthermore
When a virtual method is invoked, the run-time type of the object is
checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no
derived class has overridden the member.
protected (C# Reference)
A protected member is accessible within its class and by derived class
instances.
If you really want Method of A to be called here (without changing implementation of A or B's Method), you have to make below changes.
Change access specifier of Method of B class to new from override.
override will override the base class method. Making it new won't do it.
Change access specifier of A and B class Methods to public instead of protected
protected members of A won't be accessible inside your C class.
With this changes, check out below code. You will see that Method from class A is getting called.
static void Main()
{
var c = new C();
c.Some();
Console.ReadKey();
}
public class A
{
public virtual void Method()
{
Console.Write("A");
}
}
public class B : A
{
public new void Method()
{
Console.Write("B");
}
}
public class C : B
{
public void Some()
{
//How to call Method() from class A?
((A)this).Method();
}
}
If you cannot make the changes described as above, then I'm afraid you can't call A's Method :O .
This is impossible, because
The implementation of a virtual member can be changed by an overriding
member in a derived class.
B change implementation of A, therefore C have only B implementation as base and have not implementation of A.
Solution: https://stackoverflow.com/a/438952/8081796
Related
I have a method Hello in class A, which should be overridden by class B.
Therefore the overridden method in B has to call the base method to prepare something.
The method DoSomeThing is the additional functionality of this method. Now I want to override B.Hello in the new class C in order to change logic of B.DoSomeThing.
Requirements:
C.Hello needs the method call of A.Hello, too, in order to do some basic preparations
Only B.DoSomeThing should be replaced width new functionality, defined in C.DoSomeThing2
I am not allowed to change code inside A and B
public class A
{
protected virtual void Hello() {}
}
public class B : A
{
protected override void Hello() {
base.Hello();
DoSomeThing();
}
}
public class C : B
{
protected override void Hello() {
???????????????
DoSomeThing2();
}
}
I cannot call the base method of class A. What would be the best solution for my problem?
Simply copy and paste the code of A.Hello wouldn't work because of private methods in A.
EDIT: class C has to inherit from class B.
In C# it's possible to mark a virtual method abstract to force inherited class to implement it.
class A
{
public virtual void Method()
{
Console.WriteLine("A method call");
}
}
abstract class B : A
{
// Class inherited from B are forced to implement Method.
public abstract override void Method();
}
I would like to call the A implementation of Method from a class inherited from B.
class C : B
{
public override void Method()
{
// I would like to call A implementation of Method like this:
// base.base.Method();
}
}
The best way I find to do this is to add a protected method "MethodCore" in A implementation and call it when needed.
class A
{
public virtual void Method()
{
MethodCore();
}
protected void MethodCore()
{
Console.WriteLine("A method call");
}
}
abstract class B : A
{
public abstract override void Method();
}
class C : B
{
public override void Method()
{
MethodCore();
}
}
Is there any other way to do this ?
The best way I find to do this is to add a protected method "MethodCore" in A implementation and call it when needed.
Yes. Since you can't call an abstract method using base, all possible solutions are going to require you to eventually call Method in A using an A instance.
That said, it looks like you are looking for a way to provide a default implementation of Method in B such that any subclass of B that does not implement the method should simply use the implementation present in A. A better solution would be to not mark Method as abstract in B. Instead, make Method in B redirect to Method in A using base.Method()
abstract class B : A {
// Class inherited from B are forced to implement Method.
public virtual void Method() {
base.Method()//calls Method in A
}
}
This way, any subclass of B that wants to call Method from A can simply say base.Method().
In order to call the base virtual method from its overridden one, how should I define the instance?
Assume I have class Derived which extends Base class. I have a virtual method in Base which is overrided in class Derived.
Like this : Base instance = new Derived();
or like this: Derived instance = new Derived();
For sure I shall not use Base instance = new Based(); for it call the virtual methos and not its override.
Whether a method override calls the implementation of the base class does not depend on the type of variable you use. So, as soon as you add base.MethodName() to the implementation of the override, the first two ways you describe will be ok.
As you also mention, the third approach will not work as it does not call the overridden version of the method.
Here is a grotty way you can do that. You'll have to expose a method which calls base version. IMO don't do that. but... It is possible.
void Main()
{
B b = new B();
b.DoSomething();
b.CallAVersionDoSomething();
}
class A
{
public virtual void DoSomething()
{
Console.WriteLine("A DoSomething");
}
}
class B : A
{
public override void DoSomething()
{
Console.WriteLine("B DoSomething");
}
public virtual void CallAVersionDoSomething()
{
base.DoSomething();
}
}
Or if you want to expose it really you can expose another method in Base class which does the job for you. Here's how you go
class A
{
public virtual void DoSomething()
{
ActualDoSomething();
}
public void ActualDoSomething()
{
Console.WriteLine("A DoSomething");
}
}
class B : A
{
public override void DoSomething()
{
Console.WriteLine("B DoSomething");
}
}
and you can use instance.ActualDoSomething() which can't be overridden so you get base class version all the time.
Why does the protected method not appear?
If I make any public, internal or protected internal method they get appear.
class A
{
protected void AProtected() { }
}
class B:A
{
protected void BProtected() { }
}
class C:B
{
protected void CProtected() { }
}
class D:C
{
protected void DProtected() { }
}
class Program
{
static void Main(string[] args)
{
D classD = new D();
classD. //no method appear.
}
}
Because protected methods are accessible to the current class and subclasses of that class. Program is not a subclass of D.
Documentation
A protected member is accessible within its class and by derived class instances.
Accessibility levels
Since I notice confusion: you can call those protected methods from inside the subclass but you cannot call them from outside the subclass onto that subclass.
This might illustrate it:
Create two classes that don't have anything to do with eachother
MyMethod is NOT accessible
Add inheritance between these two classes
MyMethod IS accessible from the subclass
Try to call the method from another class
MyMethod is NOT accessible
Because that's the whole idea of protected. Protected members are only accessible by the declaring class and other classes that inherit from it.
You can find the official documentation here.
Because protected methods are not visible outside of the class or a class that inherits from that class.
From MSDN:
The protected keyword is a member access modifier.
A protected member is accessible within its class and by derived class instances.
You could call DProtected() within D, but not outside of D.
Protected is similar to private in that in can only be accessed from within the class, but has the added benefit of being accessible from inherited classes.
Your class Program (and its main method) are not able to access private or protected methods of your other classes, only public.
Protected methods can be called within derived classes only:
class A {
// This method can be called within derived classes only
protected void ProtectedA() {...}
// This method can be called within classes that are in the same namespace
internal void InternalA() {...}
// This method can be called either within derived classes only or
// within classes that are in the same namespace
protected internal void InternalOrProtectedA() {...}
}
class B: A {
protected void ProtectedB() {
// You can call A.ProtectedA() here since B is derived from A
}
}
class Program {
static void Main(string[] args)
// You can NOT call A.ProtectedA() here since B is NOT derived from A
// But you can call
// A.InternalA() since classes Program and A are in the same namespace
// A.InternalOrProtectedA() on the same reason
}
}
Another one to watch out for is if the method in the derived class is static. You can't call instance methods from a static method in a derived class, regardless of visibility/access modifiers.
If you have
namespace A
{
public class AClass
{
public void MethodCall()
{
xxx
}
}
}
Works
namespace B
{
public class BClass : A.AClass
{
public void Go()
{
A.AClass.MethodCall();
}
}
}
Doesn't Work
namespace B
{
public class BClass : A.AClass
{
public **static** void Go()
{
A.AClass.MethodCall();
}
}
}
In C#, is it possible to mark an overridden virtual method as final so implementers cannot override it? How would I do it?
An example may make it easier to understand:
class A
{
abstract void DoAction();
}
class B : A
{
override void DoAction()
{
// Implements action in a way that it doesn't make
// sense for children to override, e.g. by setting private state
// later operations depend on
}
}
class C: B
{
// This would be a bug
override void DoAction() { }
}
Is there a way to modify B in order to prevent other children C from overriding DoAction, either at compile-time or runtime?
Yes, with "sealed":
class A
{
abstract void DoAction();
}
class B : A
{
sealed override void DoAction()
{
// Implements action in a way that it doesn't make
// sense for children to override, e.g. by setting private state
// later operations depend on
}
}
class C: B
{
override void DoAction() { } // will not compile
}
You can mark the method as sealed.
http://msdn.microsoft.com/en-us/library/aa645769(VS.71).aspx
class A
{
public virtual void F() { }
}
class B : A
{
public sealed override void F() { }
}
class C : B
{
public override void F() { } // Compilation error - 'C.F()': cannot override
// inherited member 'B.F()' because it is sealed
}
You need "sealed".
Individual methods can be marked as sealed, which is broadly equivalent to marking a method as final in java. So in your example you would have:
class B : A
{
override sealed void DoAction()
{
// implementation
}
}