3

I have this setting:

public class BaseElement
{
    public BaseElement() { }
    public virtual void method01()
    {
        Console.WriteLine("class BaseElement method01");
    }
}
public class Element01 : BaseElement
{
    public Element01() { }
    public override void method01()
    {
        Console.WriteLine("class Element01 method01");
    }
}
public class Element02 : BaseElement
{
    public Element02() { }
    public override void method01()
    {
        Console.WriteLine("class Element02 method01");
    }
}

Now I want to force class Element01/Element02/Element03 and so on to implement method01. I think the correct way is to use an interface. But due to the fact that Element01/Element02/Element03 and so on inherit from BaseElement there is no need to implement method01 in Element01/Element02/Element03 and so on because it is already implemented in BaseElement. But I want to force Element01/Element02/Element03 and so on to implement a specific method01 in each of these classes. On the other hand I need method01 in BaseElement also to address Element01/Element02/Element03 and so on as BaseElement. What would be the best way to do this?

(It has nothing to do with the difference between abstract and virtual functions. I need a specific arrangement of either an interface or an abstract class.)

manton
  • 161
  • 11
  • Make the BaseElement class and the method [abstract](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/abstract)... –  Feb 15 '19 at 19:41
  • Why not make the method abstract ? – Patrick Hollweck Feb 15 '19 at 19:42
  • Possible duplicate of [What is the difference between an abstract function and a virtual function?](https://stackoverflow.com/questions/391483/what-is-the-difference-between-an-abstract-function-and-a-virtual-function) –  Feb 15 '19 at 19:42
  • Abstract method declarations are only permitted in abstract classes. May be OP do not want his base class Abstract – Pavan Chandaka Feb 15 '19 at 19:44
  • Where should I make the method abstract? In BaseElement? But how to force Element01/Element02/Element03 then to implement method01? – manton Feb 15 '19 at 19:45
  • Yes. But if you make method abstract, your class also should be abstract – Pavan Chandaka Feb 15 '19 at 19:46
  • @Naidu Correct. BaseElement should not be abstract. – manton Feb 15 '19 at 19:46
  • if you don't want to make BaseElement abstract, you have to create an Interface and Make BaseElement implement it and other child classes Inherit BaseElement and Implement Your Interface (remember new keyword when you give body to your function in child classes) – Karthik Ganesan Feb 15 '19 at 19:51
  • @KarthikGanesan, my apologies, but to be frank, your advice is terrible. Method/member hiding is not a good suggestion for the given scenario here. Also, since the base class needs to implement the interface anyway -- it cannot choose to not implement a method/member from the interface, introducing an interface does not change/solve the problem at all. –  Feb 15 '19 at 19:58
  • @manton, why should BaseElement not be abstract? –  Feb 15 '19 at 20:00
  • @elgonzo so what is your suggestion if OP says BaseElement class should not be abstract other than posting a link for difference between them? – Karthik Ganesan Feb 15 '19 at 20:00
  • 2
    @KarthikGanesan, my response to that is asking OP why? (as i did in my last comment) in an attempt to figure out what he is trying to achieve that led them to this apparent requirement of BaseElement being an instantiable class... –  Feb 15 '19 at 20:03
  • 1
    can you explain this part? *On the other hand I need method01 in BaseElement also to address Element01/Element02/Element03 and so on as BaseElement.* I don't fully understand it – iSpain17 Feb 15 '19 at 20:25
  • 1
    I think the best you can do is "abstract". If that is not appropriate you cannot force the writer of derived classes to override a virtual method, since it is up to them to decide if the default behavior provided by the base is appropriate to their needs. – Mike Feb 15 '19 at 21:01

3 Answers3

0

If I understand the question correctly you have some default behavior in base class and you need to force to implement some logic in derived class you can use Inversion of Control principle and Template method Design pattern you have to make another internal method like method01Int and it will be abstract and all derived classes should implement it for example:

 public abstract class BaseElement
{
    public BaseElement() { }
    public  void method01()
    {
        Console.WriteLine("class BaseElement method01");
        method01Int();
    }

    protected abstract void method01Int();
}
public class Element01 : BaseElement
{
    public Element01() { }
    protected override void method01Int()
    {
        Console.WriteLine("class Element01 method01");
    }
}
public class Element02 : BaseElement
{
    public Element02() { }
    protected override void method01Int()
    {
        Console.WriteLine("class Element02 method01");
    }
}

even if in derived class don't have some logic you can implement like this

    public class Element03 : BaseElement
{
    public Element03() { }
    protected override void method01Int()
    {

    }
}
Sergey K
  • 4,071
  • 2
  • 23
  • 34
  • Nice solution, thank you! I tested it and it works. But the solution below from Guillaume CR is more plain, less code and a bit easier to maintain - seems to me.I suppose I can accept only one answer ... – manton Feb 15 '19 at 22:28
  • @manton actually it is depends on what is exactly your domain model what the real sense in your classes in some cases it is not good solution in another on it could good!! And you have to think always twice when you try to introduce inheritance, because from maintainability point of view, (as you said you need solution easy maintain) inheritance not good, use composition instead!!! If you will give me your real case example I can say in more details what is better will be in your case – Sergey K Feb 16 '19 at 04:10
0

Create two interface. One for base class and another for sub classes. And implement method01() explicitly in BaseElement class. Hope it helps.

class Program
{
    static void Main(string[] args)
    {
        IBase obj = new BaseElement();
        IElement obj1 = new Element01();
        obj.method01();//call base
        obj1.method01();

        Console.ReadLine();
    }
}
public interface IBase
{
    void method01();
}
public interface IElement
{
    void method01();
}
public class BaseElement : IBase
{
    public BaseElement() { }
    void IBase.method01()
    {
        Console.WriteLine("class BaseElement method01");
    }
}
public class Element01 : BaseElement, IElement
{
    public Element01() { }
    public void method01()
    {
        Console.WriteLine("class Element02 method01");
    }

}
public class Element02 : BaseElement, IElement
{
    public Element02() { }
    public void method01()
    {
        Console.WriteLine("class Element02 method01");
    }
}
iftekhar
  • 447
  • 2
  • 8
  • But what forces the writer of Element01 to put the IElement interface in the base type list? – Mike Feb 15 '19 at 20:57
  • @imk: I tested your solution but unfortunately this won't work because I can't call method01 in BaseElement. It is required to have method01 available in BaseElement. This code will not work: Element01 el01 = new Element01(); BaseElement baseel = el01 as BaseElement; baseel.method01(); – manton Feb 15 '19 at 22:17
0

Use a MiddleElement:

public class BaseElement
{
    public BaseElement() { }
    public virtual void method01()
    {
        Console.WriteLine("class BaseElement method01");
    }
}
public abstract class MiddleElement: BaseElement
{
    public abstract override void method01();
};

public class Element01 : MiddleElement
{
    public Element01() { }
    public override void method01()
    {
        Console.WriteLine("class Element02 method01");
    }
}
public class Element02 : MiddleElement
{
    public Element02() { }
    public override void method01()
    {
        Console.WriteLine("class Element02 method01");
    }
}

That being said, I would like to understand why you have these requirements. There may be a simpler approach.

Guillaume CR
  • 3,006
  • 1
  • 19
  • 31
  • I think this solves my problem. The point is, to put an abstract class between BaseElement and the child classes. So both requirements are met: 1.) the child classes inherit from BaseElement 2.) it is ensured that method01 is implemented in every child class Thank you! I'm going to test it and after that I will accept the answer. – manton Feb 15 '19 at 22:06
  • before doing anything, you should definitely check this out: https://stackoverflow.com/questions/2118055/how-to-force-overriding-a-method-in-a-descendant-without-having-an-abstract-bas – iSpain17 Feb 16 '19 at 13:02