Abstract methods

I'd like to revive this topic with another idea of how to implement abstract methods.

In C#, abstract methods have to be members of a class that is explicitly also declared as abstract :

abstract class Command
{
    abstract internal void DoExecute();
}

In C++, declaring any method as "pure virtual", implicitly makes the class abstract :

class Command
{
  internal:
    virtual void doExecute() = 0;
};

Why do we need this type of structure?

Although protocols are able to declare "public" contracts that have to be fulfilled in implementing types, there is often the need (e.g. with frameworks) to declare a non-public contract that needs to be defined in the base class of a hierarchy but only implemented in derived classes.

Often this takes the form of a sequence of methods that are always called in the same order but whose behaviour can change according to the subclass.

public protocol CommandProtocol
{
  func execute() throws -> Bool
}

public class Command : CommandProtocol
{
  …

  public func execute() throws -> Bool
  {
    if !permitted
    {
      throw Error.executeCommandNotPermitted
    }
    
    if !enabled
    {
      throw Error.cannotExecuteDisabledCommand
    }
    
    var invocationResult = beforeExecuteEvent.invoke()

    if !invocationResult.handled
    {
      if checkBeforeExecute()
      {
        return false
      }
      
      invocationResult.success = doExecute()
    }

    if invocationResult.success
    {
      doExecuteSuccess()

      if !checkAfterExecute()
      {
        return false
      }
    }
    else
    {
      doExecuteFailure()
    }
    
    return invocationResult.success
  }
  
  …
}

In this case, the following non-public methods that we do not want to be implemented at the base class level are :

  func doExecute() -> Bool

  func doExecuteSuccess()

  func doExecuteFailure:()
  
  func checkBeforeExecute() -> Bool
  
  func checkAfterExecute() -> Bool
  

And it is how to declare such a contract, that has to be fulfilled by derived or implementing types that is missing from Swift.

I do understand that there an almost morbid fear of type-based scope but, given that the mere mention of the topic seems to invoke prevent argument, might I suggest a simple way of declaring such "pure virtual" methods in much the same way as C++?

A Working Example

At present, I use the following syntax to "emulate" C++; the only lack is the enforcement of implementation in subclasses :

public class Command
{
  …

  internal var doExecute: (() -> Bool)? { return nil }

  …
} 

This then gets overridden in a concrete subclass as :

public class ObjectCommand : Command
{
  override var doExecute: (() -> Bool)?
  {
    return {
             self.executionContext = nil
             
             self.getContextEvent.invoke(context: &self.executionContext)
             
             return self.execute?(self.executionContext) ?? false
           }
  }
}

As you can see, this uses a read-only var containing an optional closure to declare a method. The var returns nil in the case of the base class version and is similar in declaration to the C++ way of doing things.

What is Missing

As I said earlier, what is missing is the ability to force subclasses to implement this "method" with a non-nil closure.

I have a couple of suggestions :

  1. the ability to declare a protocol nested in the base class
public class Command
{
  protocol InternalExecution
  {
    func doExecute() -> Bool
    
    func doExecuteSuccess()
    
    func doExecuteFailure:()
    
    func checkBeforeExecute() -> Bool
    
    func checkAfterExecute() -> Bool
  }
}
  1. the ability to simply mark a method as abstract :
// either
public class Command
{
    func doExecute() -> Bool = nil // or 0
    
    func doExecuteSuccess() = nil
    
    func doExecuteFailure:() = nil
    
    func checkBeforeExecute() -> Bool = nil
    
    func checkAfterExecute() -> Bool = nil
  }
}
// or
public class Command
{
    abstract func doExecute() -> Bool
    
    abstract func doExecuteSuccess()
    
    abstract func doExecuteFailure:()
    
    abstract func checkBeforeExecute() -> Bool
    
    abstract func checkAfterExecute() -> Bool
  }
}

3.making it possible to declare and override an optional let to a closure :

pubic class Command
{
  internal let doExecute: (() -> Bool)? = nil
}

… to be overridden thus :

public class ObjectCommand : Command
{
  override let doExecute: (() -> Bool)? = {
                                            self.executionContext = nil
                                            
                                            self.getContextEvent.invoke(context: &self.executionContext)
                                            
                                            return self.execute?(self.executionContext) ?? false
                                          }
}

In any case, declaring such methods would both prohibit instantiation of such a class and force implementation in a subclass. Perhaps, in the last example, declaring the let as non-optional would trigger this prohibition?