-1

I'm reading the excerpt below from Joe Albahari's excellent "C# 9 in a Nutshell" and am trying to understand what's being described here in bold. Is anyone able to explain the alternative approach in a way that I can understand better? This seems somewhat backward to me for some reason.

Alternatives to interface reimplementation Even with explicit member implementation, interface reimplementation is problematic for a couple of reasons:

The subclass has no way to call the base class method.

The base class author might not anticipate that a method be reimplemented and might not allow for the potential consequences.

Reimplementation can be a good last resort when subclassing hasn’t been anticipated. A better option, however, is to design a base class such that reimplementation will never be required. There are two ways to achieve this:

When implicitly implementing a member, mark it virtual if appropriate.

When explicitly implementing a member, use the following pattern if you anticipate that subclasses might need to override any logic:

public class TextBox : IUndoable
{
  void IUndoable.Undo()         => Undo();    // Calls method below
  protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}

public class RichTextBox : TextBox
{
  protected override void Undo() => Console.WriteLine("RichTextBox.Undo");
}

If you don’t anticipate any subclassing, you can mark the class as sealed to preempt interface reimplementation.

BHoltzman
  • 11
  • 3
  • `Is anyone able to explain the alternative approach in a way that I can understand better?`Which particular aspect of the second code block doesn't make sense to you? It makes sense to me, but I am not sure what doesn't make sense to you - so I don't know what to focus on... – mjwills Aug 26 '21 at 05:52
  • Does this answer your question? [Reimplementation of inherited interface methods](https://stackoverflow.com/questions/13817978/reimplementation-of-inherited-interface-methods) and [Explicitly marking derived class as implementing interface of base class](https://stackoverflow.com/questions/46541462/) and [How to do proper Reflection of base Interface methods](https://stackoverflow.com/questions/10550970/) and [Why is a base class in C# allowed to implement an interface contract without inheriting from it?](https://stackoverflow.com/questions/2942772/) –  Aug 26 '21 at 06:24

3 Answers3

0

As I understood, what the author wants to say is that instead of hiding members of the base class, override them. Hiding is when child class has a member with the same signature, yet it's not marked virtual in the base class. i.e. if ParentClass has method A(); If you want it to be overridden by ChildClass, make A() a virtual method. Or if you don't want A() to be overridden, introduce a protected method, that A() will use and make that protected method virtual for childs to override if needed. Hope this answers your question.

David Oganov
  • 976
  • 1
  • 11
  • 23
  • This does answer my question. Thanks! The bolded sections didn't make sense to me because I didn't quite understand how the author was defining explicit and implicit implementations. It's my interpretation of what I read that was off. – BHoltzman Aug 28 '21 at 05:18
  • Glad that helped. Yes, it's a bit confusing, especially when there's no definition of the terms used. It's written in an abstract way, which may and brings confusion. It's beautiful when hard things are described in a simple way. In this case a simple thing was described in a hard way :) – David Oganov Aug 28 '21 at 07:25
0

The issue described, is that when a base class implements an interface, that base class may expect certain behaviour to occur.

The example of the textbox undo. Suppose that the base textbox does something important (or perhaps the actual work) for undoing. Also for the sake of example, assumen that when writing the base class, the author did not think of inheriting classes (richtextbox here)

He could have written it as

public class TextBox : IUndoable
{
  void IUndoable.Undo() => ....... undo logic here
}

Any inheriting class would not be able to call Undo directly (they would have to cast its base to IUndoable ) The problem now is, when other code, use the IUndo implementation (for example a menu item), the important undo in the base class would not be called, unless the inheriting class does this explicitely

Still the same with:

public class TextBox : IUndoable
{
  public void Undo() => ...... undo logic here
}

The inheriting (RichTextBox) class, could call its base when explicitly implementing Undo, but it wouldn't be sure. If RichTextBox makes its own Undo and hides the base Undo, there is no direct impulse to call the base Undo (Although more so than the first option)

In the end, what the base class author wants, is that when external code calls the IUndoable.Undo method, the required code is always called. (Side note: In an abstract class that could be handled differently, but this is a directly usable class, that may or may not be inherited)

Making the implicit implementation virtual helps a bit:

public class TextBox : IUndoable
{
  public virtual void Undo() => ...... undo logic here
}

As soon as an inheriting class overrides the method, the default snippet also calls the base class, but that is assuming the snippet is used, and base.Undo still is called, leaving the option to the inheritor.

That gives the last example as you included it:

public class TextBox : IUndoable
{
  void IUndoable.Undo()         => Undo();    // Calls method below
  protected virtual void Undo() => Console.WriteLine ("TextBox.Undo");
}

This gives a more secure option for inheriting classes to implement their own undo, without losing the undo of the base class (unless the inheriting class explicitly implements IUndoable as well, but let's not go there :P )

In the richtextbox example, the Undo is overriden, but the base Undo is not called. Exactly the sort of situation that could cause the base class implementation of 'undo' to be skipped. But here, if something (a menu item for example) calls Undo of IUndoable the explicit implementation is called, forcing the required base class undo functionality to run, but also the overriden implementation of the inheriting class (richtextbox)

Me.Name
  • 12,259
  • 3
  • 31
  • 48
  • I think this is a great explanation. Thank you Me.Name! – BHoltzman Aug 28 '21 at 05:02
  • I think my initial confusion has to do with how the explicit and implicit implementations are discussed earlier in the chapter. I don't think I quite understood that the author was talking about inheritance vs subclasses. This isn't the author's explanation so much as my tying the wrong pieces of his explanation together. – BHoltzman Aug 28 '21 at 05:08
  • You are very welcome. Regardless if it was the author's phrasing or your interpretation, this is what makes places like stackoverflow great, being able to discuss these things :) – Me.Name Aug 28 '21 at 07:23
-2

Is anyone able to explain the alternative approach in a way that I can understand better?

All it is saying is that if you try and do my below code it won't compile.

So then what are you to do if you need to use explicit interface implementation and an inheriting class needs to alter that behaviour? Well, you use the exact code you mentioned in your question. It allows you to use explicit interface implementation and allow it to be overriden.

That is it. That is all it is saying.

using System;
        
public interface IUndoable {
    void Undo();
}


public class TextBox : IUndoable
{
  void IUndoable.Undo()         => Console.WriteLine ("TextBox.Undo");
}

public class RichTextBox : TextBox
{
    void IUndoable.Undo()         => Console.WriteLine ("RichTextBox.Undo");

}

public class Program
{
    public static void Main()
    {
    }
}
mjwills
  • 23,389
  • 6
  • 40
  • 63