What do I need to do to first run the method in the base class then run the same method in the derived class? Is this a good idea?
I want run common actions in base class and extend it in the derived class in the same method. Is this how it is usually done?
public abstract class MyBase
{
void DoStuff()
{
//some common implementation
}
}
public class MyDerived : MyBase
{
void DoStuff()
{
// DoStuff in the base first
// Then DoStuff in here
}
}
are you talking about something like that?
class base
{
protected virtual void method()
{
// do some stuff in base class, something common for all derived classes
}
}
class derived : base
{
public override void method()
{
base.method(); // call method from base
// do here some more work related to this instance of object
}
}
that's not a bad idea, I do use it a lot when I have some common functionality for all derived classes.
If you want to guarantee that the base class logic is run (and not rely on the derived class being polite), you can do this:
public void Method()
{
//Stuff that should always happen in base class
OnMethod();
}
protected virtual void OnMethod()
{
//Default base class implementation that derived class can either override or extend
}
Use base.TheMethod() to run a method in the base class from a derived class.
If you want to run a method of a derived class from a base class, then you have to cast the base class to the derived class. This means that your class needs to be aware of who is deriving it, which breaks encapsulation and should be avoided.
Related
I have a C# application; There is a parent class with many child classes. I would like a method in the parent class with some logic in it, and have custom logic added to it by each child class, so that when any child class calls the method, it first runs some code defined in the parent class, and then runs the customized part of it as defined in the child class. Can this be done? If not, what is the best way to achieve this kind of code execution?
Yes, this can be done by defining a virtual method in the base class, and calling it from your "payload" method at the spot where the custom logic needs to be "plugged in". It is common to make this method abstract:
abstract class MyBase {
protected abstract void CustomLogic(); // Subclasses implement this
public void PayloadMethod() {
... // Do somethig
CustomLogic();
... // Do something else
}
}
class Derived1 : MyBase {
protected override void CustomLogic() {
... // Custom logic 1
}
}
class Derived2 : MyBase {
protected override void CustomLogic() {
... // Custom logic 2
}
}
class Derived3 : MyBase {
protected override void CustomLogic() {
... // Custom logic 3
}
}
Clients of your class hierarchy instantiate one of DerivedN classes, and call PayloadMethod(), which calls CustomLogic as part of its invocation.
This approach is called Template Method Pattern.
One way to achieve it is define a non virtual method as entry point that execute the code defined in the base class and then call a virtual (or abstract) protected method that child class can (or must) override, like this:
abstract class Foo
{
public void Bar()
{
// some code defined in the parent class
BarCore(); // the customized part of it as defined in the child class
}
protected virtual void BarCore() { }
}
The easiest way to achieve this is to have two methods:
class BaseClass
{
public void DoSomething()
{
// base class code
// derived class code, modifiable by the derived class
this.DoItSpecificallyForThatDerivedClass();
}
protected abstract void DoItSpecificallyForThatDerivedClass();
}
public class ADerivedClass : BaseClass
{
protected override void DoItSpecificallyForThatDerivedClass()
{
// code specific to this instance and/or class
}
}
I am wondering if the following code can be written in C#:
AbstractClass a = new ConcreteClass1();
a.Operations.Method1();
AbstractClass b = new ConcreteClass2();
b.Operations.Method2();
where Method1() is exclusive to the ConcreteClass1 instance and Method2() is exclusive to the ConcreteClass2() instance. As a result, a.Operations.Method2() and b.Operations.Method1() would be invalid.
This is not possible by design - a and b have the same type, and the compiler will treat them as such. The only way to make it work is by using runtime exceptions.
The concept behind using abstract classes or interfaces conflicts with what you are attempting to do; it sounds like ConcreteClass1 and ConcreteClass2 do not server the same purpose, should they still use the same abstract base class?
I don't know what exactly you are trying to do - so I'll provide a few options:
Use interfaces to show that specific classes implement specific operations:
interface IOperation1
{
void Operation1();
}
interface IOperation2
{
void Operation2();
}
Then reference the interfaces based on what you are trying to achieve.
If Method1 and Method2 are supposed to be invoked at the same time, consider a design where AbstractClass declares the method to be invoked, and the concrete classes do different operations based on that:
abstract class AbstractClass
{
...
abstract void DoSomeOperation();
}
class ConcreteClass1
{
override void DoSomeOperation()
{
this.Operations.Method1();
}
}
class ConcreteClass2
{
override void DoSomeOperation()
{
this.Operations.Method2();
}
}
It's okay for ConcreteClass1 and ConcreteClass2 to have some different methods, but share some functionality that they both inherit from AbstractClass. (If you cast them as their base type then you can only call common methods that they inherit from the base type.)
It sounds like the difference between whether a concrete class uses Method1 or Method2 is an internal detail that should be handled inside the class. The class should know what method it needs to call. In fact, does a consumer of that class even need to know that it depends on Operations? Probably not. Consumers should just call a method on the class, and then whether that class uses Operations.Method1, Operations.Method2, or even depends on Operations at all is an internal implementation detail.
Maybe what you want is something like this:
public abstract class AbstractClass
{
public abstract void DoSomething();
}
public class Operations
{
public void Method1()
{
//Does something
}
public void Method2()
{
//Apparently does something comopletely different
}
}
public class ConcreteClass1 : AbstractClass
{
private Operations _operations;
public override void DoSomething()
{
_operations.Method1();
}
}
public class ConcreteClass2 : AbstractClass
{
private Operations _operations;
public override void DoSomething()
{
_operations.Method2();
}
}
Operations should only be in the base class if it's required that every derived class will use it. (That doesn't happen too much. If all of the derived classes have the same behavior, why isn't it in the base class?) If that's the case then you can hide it in the base class, like this:
public abstract class AbstractClass
{
private Operations _operations;
protected Operations Operations { get { return _operations; } }
public abstract void DoSomething();
}
That way it's exposed to the derived classes but hidden from everything else.
First look at this code:
class Program
{
static void Main(string[] args)
{
var x =(Base) new Derived();
((IMethod)x).DoWork();
Console.ReadKey();
}
}
interface IMethod
{
void DoWork();
}
abstract class Base : IMethod
{
void IMethod.DoWork()
{
Console.WriteLine("Base.DoWork");
}
}
class Derived : Base, IMethod
{
public void DoWork()
{
//here I where I want to call base.DoWork();
Console.WriteLine("Derived.DoWork");
}
}
Output:
Derived.DoWork
Desired:
Base.DoWork
Derived.DoWork
I'm dealing with an API that exposes an interface that when implemented, the DoWork method will be called at some part of the procession.
Now in the above example, the class Base is a part of the API, that internally (in the API) already explicitly implements that interface and does some important executions in the DoWork method.
I need to override the implementation of the IMethod in my derived class as well, so I get notified when needed, the problem is I can't 'override' the method and call the base method, neither can I cast base to IMethod.
Any solution?
Note: reflection won't work since it's a Silveright project, and private method invoking is prohibited.
Are you able to just compose the classes, rather than using inheritance? Then you can implement DoWork() however you like, and still call DoWork() on the Base object as well. Since Base is abstract, you'll need to derive a dummy type to get everything to work.
class Derived : IMethod
{
private class SneakyBase : Base
{
// abstract implementations here
}
private IMethod baseObject = new SneakyBase();
void DoWork()
{
baseObject.DoWork();
// Custom DoWork code here
}
}
It's obviously a bit of pain to do things this way, but the API designers made an odd choice with the explicit interface implementation, and you're now paying for it.
Are you looking for:
public class Derived : Base
{
public override void DoWork()
{
base.DoWork();
}
}
I've found DanBryant's comment to be the answer, although as he mentions is a bit risky since we can't assure the implementer will call the base method, but is a decent way tho.
I made a protected virtual method that is called from the private interface implementer, then, in the derived class, instead of worrying about the interface, I just care about overriding the base class and calling the base implementation from it, that works perfect, example:
abstract class Base : IMethod
{
void IMethod.DoWork()
{
DoWork();
}
protected virtual void DoWork()
{
Console.WriteLine("Base.DoWork");
}
}
class Derived : Base
{
protected override void DoWork()
{
base.DoWork();
//here I where I want to call base.DoWork();
Console.WriteLine("Derived.DoWork");
}
}
I have an interface so class writers are forced to implement certain methods. I also want to allow some default implemented methods, so I create a abstract class. The problem is that all classes inherit from the base class so I have some helper functions in there.
I tried to write : IClass in with the abstract base, but I got an error that the base didn't implement the interface. Well of course because I want this abstract and to have the users implement those methods. As a return object if I use base I can't call the interface class methods. If I use the interface I can't access base methods.
How do I make it so I can have these helper classes and force users to implement certain methods?
Make sure methods in the base class have the same name as the interface, and they are public. Also, make them virtual so that subclasses can override them without hiding them.
interface IInterface {
void Do();
void Go();
}
abstract class ClassBase : IInterface {
public virtual void Do() {
// Default behaviour
}
public abstract void Go(); // No default behaviour
}
class ConcreteClass : ClassBase {
public override void Do() {
// Specialised behaviour
}
public override void Go() {
// ...
}
}
Move the interface methods into the abstract class and declare them abstract as well. By this, deriving classes are forced to implement them. If you want default behaviour, use abstract classes, if you want to only have the signature fixed, use an interface. Both concepts don't mix.
Having faced with the same problem recently, I've came up with a somewhat more elegant (to my mind) solution. It looks like:
public interface IInterface
{
void CommonMethod();
void SpecificMethod();
}
public abstract class CommonImpl
{
public void CommonMethod() // note: it isn't even virtual here!
{
Console.WriteLine("CommonImpl.CommonMethod()");
}
}
public class Concrete : CommonImpl, IInterface
{
void SpecificMethod()
{
Console.WriteLine("Concrete.SpecificMethod()");
}
}
Now, according to C# spec (13.4.4. Interface mapping), in the process of mapping IInterface on Concrete class, compiler will look up for CommonMethod in CommonImpl too, and it doesn't even have to be virtual in the base class!
The other significant advantage, compared to Mau's solution, is that you don't have to list every interface member in the abstract base class.
I am creating an object structure and I want all sub classes of the base to be forced to implement a method.
The only ways I could think of doing it were:
An abstract class - Would work but the base class has some useful helper functions that get used by some of the sub classes.
An interface - If applied to just the base class then the sub classes don't have to implement the function only the base class does.
Is this even possible?
N.B. This is a .NET 2 app.
You can have abstract methods in a class with other methods that are implemented. The advantage over an interface is that you can include some code with your class and have the new object be forced to fill in the details for the abstract methods.
public abstract class YourClass
{
// Your class implementation
public abstract void DoSomething(int x, int y);
public void DoSomethingElse(int a, string b)
{
// You can implement this here
}
}
An abstract class - Would work but the
base class has some useful helper
functions that get used by some of the
sub classe
An abstract class doesn't require all functions it provides to be abstract.
abstract class Base {
public void Foo() {} // Ordinary method
public virtual void Bar() {} // Can be overridden
public abstract void Xyz(); // This one *must* be overridden
}
Note that if you replace public with protected, the marked method will be only visible to base classes and subclasses.
An interface - If applied to just the
base class then the sub classes don't
have to implement the function only
the base class does.
This is not entirely correct. If the base class is abstract, you can mark methods that belong to the interface as abstract, and force the implementation in the subclasses.
That brings an option you didn't mention: to use both. You have an IFoo interface, and a FooBase abstract base class the implements it, or part of it. This provides subclasses with a "default" implementation of the interface (or part of it), and also lets you inherit from something else and still implement the interface, or if you want to implement the interface but not inherit the base class implementation. An example might help:
// Your interface
interface IFoo { void A(); void B; }
// A "default" implementation of that interface
abstract class FooBase : IFoo
{
public abstract void A();
public void B()
{
Console.WriteLine("B");
}
}
// A class that implements IFoo by reusing FooBase partial implementation
class Foo : FooBase
{
public override void A()
{
Console.WriteLine("A");
}
}
// This is a different class you may want to inherit from
class Bar
{
public void C()
{
Console.WriteLine("C");
}
}
// A class that inherits from Bar and implements IFoo
class FooBar : Bar, IFoo
{
public void A()
{
Console.WriteLine("Foobar.A");
}
public void B()
{
Console.WriteLine("Foobar.B");
}
}
Yes, and if all the classes you need to do this for are logically subclasses of an existing abstract base class, then add an abstract method to the base class... This is better than an interface because it allows you to add implementation later (by changing abstract base class method to virtual method with a default implementation), if/when it turns out that, say, eight of ten derived classes will have the same implementation, and say, only two of them differ...
EDIT: (based on thread in comments below) The base class must be declared as abstract to do this... You can't have an abstract method in a non-abstract class because a non-abstract class can be instantiated, and if an instance of it was created, there wouldbe NO implementation for that method. So this is illegal. By declaring the base as abstract, you inhibit instantiation of the class. Then, only non-abstract derived classes can be instantiated, where, (because the base method is abstract) you MUST add an implementation for that method.
And full worker sample with params (.netcore 2.2):
class User{
public string Name = "Fen";
}
class Message{
public string Text = "Ho";
}
// Interface
interface IWorkerLoop
{
// Working with client message
string MessageWorker(string msg);
}
// AbstractWorkerLoop partial implementation
public abstract class AbstractWorkerLoop : IWorkerLoop
{
public User user;
public Message msg;
// Append session object to loop
public abstract AbstractWorkerLoop(ref User user, ref Message msg){
this.user = user;
this.msg = msg;
}
public abstract string MessageWorker(string msg);
}
// Worker class
public class TestWorkerLoop : AbstractWorkerLoop
{
public TestWorkerLoop(ref User user, ref Message msg) : base(user, msg){
this.user = user;
this.msg = msg;
}
public override string MessageWorker(string msg){
// Do something with client message
return "Works";
}
}