0

Please note in advance that this is a code written for learning purposes. Please look at the flow rather than the direct implementation :D


I have a FileHandler that simply reads and writes files.

public class FileHandler : IReadAndWriteHandler
{
    private const string Path = @"C:\Temp\tempFile.txt";
    
    public void Write(string message)
    {
        using var writer = new StreamWriter(Path);
        writer.WriteLine(message);
    }

    public string Read()
    {
        using var reader = new StreamReader(Path);
        
        return  reader.ReadLine();
    }
}
public interface IReadAndWriteHandler
{
    public void Write(string message);
    public string Read();
}

To extend the functionality, we decide to use the Decorator pattern. So, I wrote a decorator like this:

public abstract class HandlerDecorator : IReadAndWriteHandler
{
    private readonly IReadAndWriteHandler _handler;

    protected HandlerDecorator(IReadAndWriteHandler handler)
    {
        _handler = handler;
    }
    
    public virtual void Write(string message)
    {
        _handler.Write(message);
    }

    public virtual string Read()
    {
        return _handler.Read();
    }
}

Now we can extend our functionality by inheritance our decorator. I wrote an EncryptionHandlerDecorator that does encryption. But I accidentally forgot to override Read().

public class EncryptionHandlerDecorator : HandlerDecorator
{
    public EncryptionHandlerDecorator(IReadAndWriteHandler handler)
        : base(handler)
    {
        
    }

    public override void Write(string message)
    {
        base.Write(Encrypt(message));
    }

    private static string Encrypt(string message) => $"Encrpyt({message})";
}

However, It doesn't raise an error at compile-time, so it works fine. Very sadly, when you actually use it, the encrypted content is read, so it's wrong code.

To solve this, there is a way to directly implement one by one without using an abstract class, but that is not the point of this question right now.

If I don't override a virtual method defined in an abstract class, is there a way to raise an error at compile-time like an interface?

isakgo_
  • 750
  • 4
  • 15
  • This largely depends on your IDE. I believe in most you can redefine how the IDE reacts to a certain "trigger". And most have a trigger on this, because many, if not all IDE's mark the virtual keyword as "grey", if you do not have an overload. However. I am not certain about this. I would take a look at your IDE's online documentation. – Morten Bork Sep 04 '22 at 07:50
  • Why don't you made the method abstract? – Turo Sep 04 '22 at 07:53
  • @MortenBork I'm currently using **Rider**, so I'll ask **JetBrains** as you say. Thanks for the good info :D – isakgo_ Sep 04 '22 at 07:53
  • @Turo I don't understand, can you explain a little bit longer? – isakgo_ Sep 04 '22 at 07:54
  • 3
    Why didn't you just define the method in the abstract class?: `public abstract string Read();` – Turo Sep 04 '22 at 07:56
  • @Turo Wow! Why didn't I just think of creating an abstract method? Thanks to your insight, the problem is solved. – isakgo_ Sep 04 '22 at 08:04

1 Answers1

2

You're probably looking for abstract methods, which requires derived classes to implement the function. However, you'll need to define internal scoped functions, so derived classes can write to the handler itself, as the base implementation will no longer be available to it.

public abstract class HandlerDecorator : IReadAndWriteHandler
{
    private readonly IReadAndWriteHandler _handler;

    protected HandlerDecorator(IReadAndWriteHandler handler)
    {
        _handler = handler;
    }
    
    public abstract void Write(string message);

    public abstract string Read();

    internal void WriteRaw(string message)
    {
        _handler.Write(message);
    }

    internal string ReadRaw()
    {
        return _handler.Read();
    }
}
r0den
  • 382
  • 1
  • 14