Have a class conform to protocols privately

Is it possibel to create a class that conforms to protocols without clients of this class knowing about this coformance?

I want o achieve what I would achien in Objective-C by adding in the .m file the following code:


// .m file
@interface MyClass () <SomeProtocol>
@end

How to do this in Swift?


The following gives me an error:

"'Private' modifier cannot be used with extensions that declare protocol conformances."

private extension MyClass:
    SomeProtocol
{
}
public class MyClass : NSObject
{
}

Accepted Reply

I assume since you say "when attempting to build" that the compiler is crashing – that is definately something you should file, as The Compiler Should Never Crash™ 🙂.


I don't have any special insight into why Swift doesn't allow private conformance, but I do have extensive experience these types of issues in larger source bases. The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations.


For example, you have a class that privately conforms to a protocol and implements all of its methods. Later a subclass comes along and wants to do the same, but only wants to implement the required methods (because the optional ones not being implemented might provide some default behavior that subclass wants). But now you have 2 problems:


1) The object expecting this protocol implementation now has possibly 2 consumers of the protocol on the same object. This leads to both objects having to guard against unexpected calls. Or none, as due to the private conformance, the subclass can't call super to resolve the unexpected calls.


2) There is no way for the subclass to get the behavior it wants without modifying the protocol, as the superclass's implementation can't be removed without affecting its behavior either.


Overall the private class that calls back up to its owning class solves these issues by ensuring that only the exact implementation as desired is used for the delegate, and by virtue of being a private class it cannot be externally subclassed either. Similarly if you have a number of classes that might want to share the logic of this private class, you can instead make it internal and share the common logic, which is a lot easier than reimplementing that logic in each class that wants to conform to that delegate.


Overall it is harder to do than simply provide private conformance, and in many cases this is way overkill for what you want to do.


HTH.

Replies

You can create a helper object that implements the protocol and messages back to its parent.

Edit:

My proposed solution actually does not compile: it will lead to a segmentation fault 11 when I try building this.


Yes that is one option, but it seems a bit kludgy to me.

I've come up with a solution that I like better: I create a public class (basically what would in Objective-C be the .h file), and then privately I subclasst this public class, mark the subclass as private and implement the protocol methods which now are not require to be public. Do you see any disadvantages in that? I've posted below what I mean.


Was there a reasoning behind why this has to be done in such a, what seems to me, kludgy way in Swift? I'm sure there must have been good reasons for it, or should I file a radar?


public class MyClass : NSObject
{
}
private class MyClassPrivate : MyClass,
     SomeProtocol
{
}

I assume since you say "when attempting to build" that the compiler is crashing – that is definately something you should file, as The Compiler Should Never Crash™ 🙂.


I don't have any special insight into why Swift doesn't allow private conformance, but I do have extensive experience these types of issues in larger source bases. The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations.


For example, you have a class that privately conforms to a protocol and implements all of its methods. Later a subclass comes along and wants to do the same, but only wants to implement the required methods (because the optional ones not being implemented might provide some default behavior that subclass wants). But now you have 2 problems:


1) The object expecting this protocol implementation now has possibly 2 consumers of the protocol on the same object. This leads to both objects having to guard against unexpected calls. Or none, as due to the private conformance, the subclass can't call super to resolve the unexpected calls.


2) There is no way for the subclass to get the behavior it wants without modifying the protocol, as the superclass's implementation can't be removed without affecting its behavior either.


Overall the private class that calls back up to its owning class solves these issues by ensuring that only the exact implementation as desired is used for the delegate, and by virtue of being a private class it cannot be externally subclassed either. Similarly if you have a number of classes that might want to share the logic of this private class, you can instead make it internal and share the common logic, which is a lot easier than reimplementing that logic in each class that wants to conform to that delegate.


Overall it is harder to do than simply provide private conformance, and in many cases this is way overkill for what you want to do.


HTH.

Thank you for your detailed explanation. I will go for composition as it seems to be the most robust solution.

It makes more sense now, although I am still not convinced that using Swift will lead to a better architectur of apps; these kind of issues tend to make people take the easy way and just have a class expose more then strictly needed. I guess with time we might get better options (eventually we are going to have to build frameworks with Swift, so we are going to need header files then).

All this talk of protocols and private/public reminds me of another thing that's been bugging me lately. Why does conforming to a protocol require that all the methods to achieve said conformance be made public? In Objective-C, declaring that an object conforms to a protocol in the header file was enough; if protocol Foo defines required methods -bar and -baz, then just seeing that some object implements Foo was all you needed to see in ordrer to know that you could call -bar and -baz on that method, without having to clutter up the header file with definitions of -bar and -baz. This was nice since many of the methods defined by protocols in Cocoa are intended to be called by the framework, rather than directly by your object's clients, so having them visible in the interface would serve only to distract users from the methods they areactually supposed to call. In Swift, though, all protocol methods have to be public, which means they'll all show up in the generated header files and clutter everything up.


Same goes for overriding methods, really. If a method overrides some superclass method as an implementation detail, and that method isn't intended to be called directly by clients, why does the override have to be in the public interface?