OK, here comes the girl with the big wooden spoon to stir things up a bit ;-)

When it comes to visibilities on classes, why, oh why do we have public vs open 
*as well as*
 the option of marking stuff as final?

Surely, outside the module boundary :

1. public is the same as final ; i.e. you can see it but you can't derive 
from/override it

2. open is the same as public without final ; you can see it and derive 
from/override it

Inside the module boundary, there is essentially no difference between public 
and open.

In fact, open/public is a conflation of concerns.

Both allow public visibility but, mixed in with that is restriction of 
inheritance. Surely public is good enough for visibility and final is good 
enough for inheritance restriction?

////////////////
// Module1 file

// MARK: base classes

open class OpenClass
{
  open func test() { }
}

public class PublicClass
{
  public func test() { }
  
  public final func finalTest() { }
}

public final class FinalPublicClass
{
  public final func test() { }
}

// MARK: derived internal classes

class FrameworkDerivedPublicClass : PublicClass
{
  override func test() { }
  
  override func finalTest() { } // error : instance method overrides a 'final' 
instance method
}

class FrameworkDerivedFinalPublicClass : FinalPublicClass // error : 
inheritance from a final class
{
  override func test() { } // error : instance method overrides a 'final' 
instance method
}
///////////////

///////////////
// Module2 file

class OpenSubclass : OpenClass
{
  override func test() { }
}

class PublicSubclass : PublicClass // error : cannot inherit from non-open 
class 'PublicClass' outside of its defining module
{
  override func test() { } // error : overriding non-open instance method 
outside of its defining module
  
  override func finalTest() { } // error : method does not override any method 
from its superclass
}

class FinalPublicSubclass : FinalPublicClass // error : cannot inherit from 
non-open class 'FinalPublicClass' outside of its defining module
{
  override func test() { } // error : instance method overrides a 'final' 
instance method
                                           // error : overriding non-open 
instance method outside of its defining module
}
////////////////

In fact, the test() method in FinalPublicSubclass gives two errors one of which 
is the same as when declared in FrameworkDerivedFinalPublicClass.

If final is good enough for inside the module boundary, and the same 
"overriding final method" error appears in both places, do we really need this 
added complexity?

Surely, if we take public as meaning no inheritance control anywhere :

public class BaseClass
{
  public func test() { }
  
  public final func finalTest() { }
}

And then, either in or out of the module :

class DerivedClass : BaseClass
{
  override func test() { }
  
  override func finalTest() { } // error : instance method overrides a 'final' 
instance method
}

Or, if BaseClass were marked as final, then inheritance of the whole class is 
prohibited.

So, I am proposing a reduction in keywords from open, public and final, to just 
public and final.

--
Joanna Carter
Carter Consulting

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to