Nested classes

Hi all,

Here is a case that I would like to share with you
I have a base class that contains other classes that contain other subclasses as the following pseudo code

// File: Base.swift
public class Base {
    public class Class {
        public class SubClass {
        }
    }
}

With time my class Base gets bigger I decided to split the sources like this

// File: Base.swift
public class Base {
}

// File: Base.Class.swift
public extension Base {
    public class Class {
        public class SubClass {
        }
    }
}

All goes well but I want to go further. I would like each class to be on its own file but I can not.

// File: Base.swift => OK
public class Base {
}

// File: Base.Class.swift => OK
public extension Base {
    public class Class {
    }
}

// File: Base.Class.SubClass.swift => Error: Declaration is only valid at file scope
public extension Base {
    public extension Class {
        public class SubClass {
        }
    }
}

I also tried

// File: Base.Class.SubClass.swift => Error: 'Class' is not a member type of 'Base'
public extension Base.Class {
    public class SubClass {
    }
}

When I define the class Base, Class and SubClass in the same file it is not a problem. Base and Class in their own file it's good too. But it does not work for SubClass.
I do not understand this limitation (?!?!?)
Is there any trick or syntax to do what I'm trying to do?

Are you sure that the final thing you tried doesn't work?

My build succeeds with

// file 1
public class Base {}

// file 2
public extension Base {
    public class Class {}
}

// file 3
public extension Base.Class {
    public class SubClass {}
}

It's an old and well-known bug (SR-631) that was recently fixed thanks to @Slava_Pestov. I assume the changes should have already been integrated into the latest Xcode beta build.

There's a separate issue causing some problems though (see https://github.com/apple/swift/pull/18168).

2 Likes

I just try with Xcode 10 Beta 6 and Swift 4.2 and the error still exist

@Tof Extensions cannot be nested, try fixing that to see if it works.

My test project was created with Xcode 9.4.1
At my first try with Xcode 10 I changed the swift language to swift 4.2 and the test failed
I recreate the test project from scratch with Xcode 10 beta 6 and... it is working now (?!?!?!)


Just strange... :thinking:

This change was only made on master, and not the swift-4.2-branch.

1 Like
// file 1
public class Base {}

// file 2
public extension Base {
    public class Class {}
}

// file 3
public extension Base.Class { // <= Error: 'Class' is not a member type of 'Base'
    public class SubClass {}
}

I tried to apply this template on real class on a project that I migrate to Xcode 10 Beta 6 and swift 4.2
The error is back:

'Class' is not a member type of 'Base'

Do I have this error because the project was originally on Xcode 9.4.1?
Is there a specific setting to specify at the project level?

See the response in the previous message in this thread: Nested classes. The change is on master branch only, not on swift 4.2 branch.

Excuse me if I have trouble understanding but why put this patch in master and not the branch swift-4.2-branch?
Personally on my projects I never work directly on the master. I am doing the evolutions / fixes in branches. I only update the master once the evolutions / fixes are good.
Does this mean this fixe will not be put in the release of Swift 4.2 with Xcode 10?

It does mean exactly that. The subclass issue I filed (SR-5993) is only fixed in Swift 5. Here the conversation from Twitter.

To provide some more context: the primary purpose of the release branches is to have something "converge" to a stable implementation over the last part of a release. That's why we have more process about changing things there than on master. Since any change can introduce new bugs, bringing a fix to the release branch has to be considered worth the possible risk; that "high value / low risk" requirement gets stricter as the release goes on.

In this case, the bug stinks, but it's also been around for a long time and has several established workarounds. Therefore, the risk of possible new bugs outweighs the benefit of trying to backport the fix to the 4.2 branch. Sorry!

2 Likes