Why can't Protocols be nested in other Types?

We can nest classes, structs & enums:

class TestClass {
     class OtherClass {}
     struct OtherStruct {}
     enum OtherEnum {}
}


Why can't we also nest protocols?

class TestClass {
     protocol Delegate {}  // error: Declaration is only valid at file scope
}


So far the workaround is to declare it at file scope using and use a typealias instead.

The underscore prefix makes it clear that the global symbol name is not intended for direct use.

class TestClass {
     typealias Delegate = _TestDelegate
}

protocol _TestDelegate {}


Is this just not yet implemented or is there a reason for not supporting that at all?

What I fail to understand is why you want to abstract it out of the class the first place. It's just a single method.


And as a second point: protocols are intended, as in Obj-C, to define behaviour like compareable. It is not a poor mans multiple inheritance as interfaces in java or c++.

Concrete example:


I have a project with a large codebase (> 100s of classes/types). One of these types is a Script-Runner class, with public (internal) interfaces, and several internal (private) classes, including a large, complex script parser which runs to nearly 2500 LOC.


Now, the Script-Runner is the only thing that needs access to the parser and its related internal types, but these types are not completely severable from the rest of the application (they need access to various types within the rest of the codebase for utility, context, etc). In current Swift, I have only two unpleasant choices:


  1. pollute the whole application's namespace with many dozens of type names, protocols, methods, variables, etc which serve no purpose outside of this script parsing functionality
  2. put these types in a single file (to make use of 'private') resulting in a massive 4000 LOC file


I've chosen #2 as the least onerous, but that doesn't mean it's a good solution.

I see #2 as the good solution. I never got where that madness of 1 class = 1 file came from. But the problem sounds like a perfect fit for a framework.

Not a good fit because there are cross-dependencies. The private code is not easily factorable into a framework independent of the rest of the application, and trying to extract it would rapidly devolve into a nightmare of framework dependencies.


I'm not super-strict about 1 class = 1 file, but I strongly dislike being forced into using source files to impart syntactical structure. Where does it end? If I need to increase the complexity of the script parser, should I have a 10k-line file? 20k? That's absurd. In a modern language, why should file boundaries be the only viable tool for managing encapsulation?

I think in this case "Factory" can be a nested type, some struct ou some anonymous enum (without case).


class Foo {
  enum Factory {
    static func newFoo(x: Int, _ y: Int) -> Foo {
        //...
        return Foo();
    }
  }
//...
}
class Bar {
  enum Factory {
    static func newBar(string: String) -> Bar {
        //...
        return Bar();
    }
  }
//...
}

var tBar = Bar.Factory.newBar("someString");

It appears from the info you have given, that your code is way to tighly coupled. No form of namespacing will remove that design error.


And why a file as scope? Because it is a natural unit of code. Many languages use file based scope, just not C/C++. Pascal units, Modula/Oberon modules, Python modules etc.

Why not simply so?


class Foo {
  static func new(x: Int, _ y: Int) -> Foo {
    return Foo()
  }
}

class Bar {
  static func new(string: String) -> Bar {
    return Bar()
  }
}

var tBar = Bar.new("something")


And please don't use ; as line ending in Swift 🙂

pontificate if you like, but it's not a design error... its the nature of the problem domain. The script parsing is directly related and tightly coupled to information available from the rest of the application. Just because you don't understand the architecture from my brief description doesn't make it invalid.

That goes against all of my knowlegte of parsing theory - tighlly coupling to the internal data structures sound like a sure way to trouble.


Anyway, if your code is or requieres such tight coupling huge compilation units are the logical result. You have to keep all related stuff together.

This is what generally i do... I dont like the idea to make the FactoryType or similar... But some people like.

The protocols from my example could be used in an abstract factory-based design. Abstract factory is one of the most basic design patterns. If you use it or not, this is considered good software design.

Factory is a very widely used pattern *in Java*. It is far from a general good practice in oop design. Yes, it is a basic pattern but it is totally overused and makes simple code often much more complex. Do I really have to point to Factory Factories in Java?

Btw, the problem also exists in the opposite direction:

protocol Parser {
    func parse() throws -> Node

    enum Error {}
    protocol Node {}
}


You cannot declare types inside a protocol, which is a pity if you want good abstraction and good namespacing at the same time.


This will work though:

class Parser {
    func parseNode() throws -> ParserNode {}

    enum Error {}
}


protocol ParserNode {}

Well Swift protocols aren't designed to provide abstraction and namespacing. Of course they will have problem if you try to use them in this manner.


The namespacing mechanism in Swift are modules and for abstraction generic classes with inheritance.

Sorry but this is nonsense.


You're basically saying that nested types are a bug in Swift rather than a feature.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/NestedTypes.html


So far some types support nesting while others don't. So we can consider cases which are not possible at the moment to be a temporary limitation.

Why can't Protocols be nested in other Types?
 
 
Q