How to do?I want a protocol that can only be followed by two classes - swift

I want a protocol that can only be followed by two classes。(ClassA or ClassB).
protocol MyProtocol where Self: ClassA || ClassB {
}

This requirement almost certainly indicates a design problem. If any piece of your system cares what is implementing the protocol, then the protocol does not capture the whole interface. For example, if at any point you use as? ClassA, then this is a dangerous use of protocols.
It is impossible in Swift to have a protocol that I can see but that I cannot implement. There are languages like Go where it's possible (though still not in exactly the way you describe), but it's impossible in Swift today. As #MartinR notes, the answer by J. Doe doesn't actually change anything. Outside parties can still just implement both protocols.
With that said, it's possible to achieve things very similar to what you're describing.
First, and most obviously: use access controls.
private protocol MyProtocol {}
public class ClassA: MyProtocol {}
public class ClassB: MyProtocol {}
This works if all the classes and protocol are in one file. If not, put them all in a framework and use internal rather than private. Now nothing outside this file/module can implement MyProtocol. The limitation is that MyProtocol is also can't be seen outside the file/module.
This can be resolved by lifting a struct:
public struct MyStruct: MyProtocol {
private let value: MyProtocol
public init(classA: ClassA) { value = classA }
public init(classB: ClassB) { value = classB }
// Methods to conform to MyProtocol by forwarding to value
}
With this, it's impossible to generate a MyStruct that is initialized with anything but a ClassA or ClassB.
Alternately, if you really literally mean "ClassA or ClassB" that's not a struct or a protocol. That's a enum:
enum MyEnum {
case classA(ClassA)
case classB(ClassB)
}

Related

What's the point of conforming to an empty protocol in Swift

I'm just working on a codebase where the most classes conform to an empty protocol. Is there any point of doing so? Actually conforming that protocol does nothing.
Edit as reaction to #vacawama's helpful comment : the protocol is only used once
import Foundation
protocol myUrlRequestConfig {}
extension myUrlRequest: myUrlRequestConfig {
public static func configGetAppConfig() -> URLRequest {
let request = ....
return request
}
}
An empty protocol can be useful if you want to create an easy way to add static functions or variables to several different classes. Of course, this only makes sense if the static functionality is the same for all classes conforming to the protocol.
Here is an example: I have a protocol sizeable. Every class that conforms to Sizeable is extended with the static variable stride and size.
protocol Sizeable { }
extension Sizeable {
static var size: Int {
return MemoryLayout<Self>.size
}
static var stride: Int {
return MemoryLayout<Self>.stride
}
}
class Foo: Sizeable {}
class Baa: Sizeable {}
Foo.size
Baa.size
Our app has three perfectly legitimate uses for an empty protocol:
The protocol has an extension with method definitions. The implementation in the extension is automatically injected into any type that adopts the protocol.
The protocol has other protocols that adopt it. This allows multiple protocols to be unified under a single head.
The protocol marks the adopter as wanting some other type to behave in a certain way. Code can always is whether an object is ThisEmptyProtocol and if it is, can behave differently than if it isn't.

Swift protocol to only implemented by specific classes

I want to create a protocol which is only adopted by a specific class and its subClassses in swift.
I know i can use protocol extensions like this
protocol PeopleProtocol: class {
}
extension PeopleProtocol where Self: People {
}
But the method that will go in my protocol will be an init method which will be implemented by a class or its subClasess and will return only some specific type of objects.
some thing like this.
protocol PeopleProtocol: class {
init() -> People
}
or i can do some thing like this
extension PeopleProtocol where Self : People {
init()
}
But there are two problems,
In the first approach if i put an init method in the protocol it don't allow me to put a return statement there like -> People in the first approach.
In the second approach i have to provide a function body in the protocol extensions, so this thing will be out of question, as i don't know what specific type to return for this general implementation.
So any suggestions how i can call an init method and do either:
Let the protocol (not protocol extension) to be implemented by only specific classe and its subClasses.
Or return an instance of a certain from protocol extension method without giving its body.
You could add a required method that you only extend for the appropriate classes.
for example:
protocol PeopleProtocol
{
var conformsToPeopleProtocol:Bool { get }
}
extension PeopleProtocol where Self:People
{
var conformsToPeopleProtocol:Bool {return true}
}
class People
{}
class Neighbours:People
{}
extension Neighbours:PeopleProtocol // this works
{}
class Doctors:People,PeopleProtocol // this also works
{}
class Dogs:PeopleProtocol // this will not compile
{}
This could easily be circumvented by a programmer who would want to, but at least it will let the compiler warn you if you try to apply the protocol to other classes.

Swift: Is it possible to add a protocol extension to a protocol?

Lets say I have two protocols:
protocol TheirPcol {}
protocol MyPcol {
func extraFunc()
}
What I want to do is to create a protocol extension for 'TheirPcol' which lets extraFunc() work on anything which conforms to 'TheirPcol'. So something like this:
extension TheirPcol : MyPcol { // Error 'Extension of protocol 'TheirPcol' cannot have an inheritance clause.
func extraFunc() { /* do magic */}
}
struct TheirStruct:TheirPcol {}
let inst = TheirStruct()
inst.extraFunc()
The kicker in this is that 'TheirPcol', 'TheirStruct' are all handled by an external API which I do not control. So I'm passed the instance 'inst'.
Can this be done? Or am I going to have to do something like this:
struct TheirStruct:TheirPcol {}
let inst = TheirStruct() as! MyPcol
inst.extraFunc()
It seems there are two use-cases of why you may want to do what you are doing. In the first use-case, Swift will allow you to do what you want, but not very cleanly in the second use-case. I'm guessing you fall into the second category, but I'll go through both.
Extending the functionality of TheirPcol
One reason why you might want to do this is simply to give extra functionality to TheirPcol. Just like the compiler error says, you cannot extend Swift protocols to conform to other protocols. However, you can simply extend TheirPcol.
extension TheirPcol {
func extraFunc() { /* do magic */ }
}
Here, you are giving all objects that conform to TheirPcol the method extraFunc() and giving it a default implementation. This accomplishes the task of extending functionality for the objects conforming to TheirPcol, and if you want it to apply to your own objects as well then you could conform your objects to TheirPcol. In many situations, however, you want to keep MyPcol as your primary protocol and just treat TheirPcol as conforming to MyPcol. Unfortunately, Swift does not currently support protocol extensions declaring conformance to other protocols.
Using TheirPcol objects as if they were MyPcol
In the use case (most likely your use case) where you really do need the separate existence of MyPcol, then as far as I am aware there is no clean way to do what you want yet. Here's a few working but non-ideal solutions:
Wrapper around TheirPcol
One potentially messy approach would be to have a struct or class like the following:
struct TheirPcolWrapper<T: TheirPcol>: MyPcol {
var object: T
func extraFunc() { /* Do magic using object */ }
}
You could theoretically use this struct as an alternative to casting, as in your example, when you need to make an existing object instance conform to MyPcol. Or, if you have functions that accept MyPcol as a generic parameter, you could create equivalent functions that take in TheirPcol, then convert it to TheirPcolWrapper and send it off to the other function taking in MyPcol.
Another thing to note is if you are being passed an object of TheirPcol, then you won't be able to create a TheirPcolWrapper instance without first casting it down to an explicit type. This is due to some generics limitations of Swift. So, an object like this could be an alternative:
struct TheirPcolWrapper: MyPcol {
var object: MyPcol
func extraFunc() { /* Do magic using object */ }
}
This would mean you could create a TheirPcolWrapper instance without knowing the explicit type of the TheirPcol you are given.
For a large project, though, both of these could get messy really fast.
Extending individual objects using a child protocol
Yet another non-ideal solution is to extend each object that you know conforms to TheirPcol and that you know you wish to support. For example, suppose you know that ObjectA and ObjectB conform to TheirPcol. You could create a child protocol of MyPcol and then explicitly declare conformance for both objects, as below:
protocol BridgedToMyPcol: TheirPcol, MyPcol {}
extension BridgedToMyPcol {
func extraFunc() {
// Do magic here, given that the object is guaranteed to conform to TheirPcol
}
}
extension ObjectA: BridgedToMyPcol {}
extension ObjectB: BridgedToMyPcol {}
Unfortunately, this approach breaks down if there are a large number of objects that you wish to support, or if you cannot know ahead of time what the objects will be. It also becomes a problem when you don't know the explicit type of a TheirPcol you are given, although you can use type(of:) to get a metatype.
A note about Swift 4
You should check out Conditional conformances, a proposal accepted for inclusion in Swift 4. Specifically, this proposal outlines the ability to have the following extension:
extension Array: Equatable where Element: Equatable {
static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool { ... }
}
While this is not quite what you are asking, at the bottom you'll find "Alternatives considered", which has a sub-section called "Extending protocols to conform to protocols", which is much more what you're trying to do. It provides the following example:
extension Collection: Equatable where Iterator.Element: Equatable {
static func ==(lhs: Self, rhs: Self) -> Bool {
// ...
}
}
Then states the following:
This protocol extension would make any Collection of Equatable elements Equatable, which is a powerful feature that could be put to good use. Introducing conditional conformances for protocol extensions would exacerbate the problem of overlapping conformances, because it would be unreasonable to say that the existence of the above protocol extension means that no type that conforms to Collection could declare its own conformance to Equatable, conditional or otherwise.
While I realize you're not asking for the ability to have conditional conformances, this is the closest thing I could find regarding discussion of protocols being extended to conform to other protocols.

Why use class only protocols in Swift?

Can anyone please explain class only protocols to me in Swift. I understand what protocols are and why we use them. I also understand that its recommended to use class only protocols when we use reference type objects in it and want to limit the protocol conformation to classes only. However, I can't find any good answer to support that recommendation. Why is it recommended? What is the drawbacks of using normal protocols in that case.
One use case:
You have a "delegate" protocol and someone wants to have a weak property of that protocol type. weak can only be used on reference types; therefore, the protocol must be class-only.
Another use case used to be to extend reference types to adopt protocols. You can't extend AnyObject itself (to inherit from another protocol, or for any other reason) but you have any reference types you want adopt a protocol inherited from AnyObject.
For example, having class equality based on unique identity is often a perfectly fine solution, so you could adopt EquatableObject:
public protocol EquatableObject: AnyObject, Equatable { }
public extension EquatableObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}
But now, we have protocol extension constraints (using where clauses), so instead of extending AnyObject, we can extend the protocol, and use AnyObject as a constraint. It looks backwards but operates identically, and removes the need for our own protocol. 🥳
public extension Equatable where Self: AnyObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}

Swift: Property conforming to a specific class and in the same time to multiple protocols

In Objective-C, it's possible to write something like that:
#property(retain) UIView<Protocol1, Protocol2, ...> *myView;
But how can I write this code in swift?
I already know how to make a property conform to many protocols, but it does not work by using the inheritance:
var myView: ??? protocol<Protocol1, Protocol2, ...>
Edit:
I use many UIView subtypes like UIImageView, UILabel or others, and I need to use some of the UIView properties plus some methods defined in the protocols. In the worst case I could create a UIViewProtocol with the needed properties, but I would know if it is possible in Swift to declare a property/variable with a type and some protocol to conform with.
You can do this with a generic class using a where clause:
A where clause enables you to require that an associated type conforms
to a certain protocol, and/or that certain type parameters and
associated types be the same.
To use it, make the class your property is defined in a generic class with a type constraint to check if the type parameter for your property matches your desired base class and protocols.
For your specific example, it could look something like this:
class MyViewController<T where T: UIView, T: Protocol1, T: Protocol2>: UIViewController {
var myView: T
// ...
}
In Swift 4 it's finally possible. You can declare variable of some class conforming to protocol at the same time, like this:
class ClassA {
var someVar: String?
}
protocol ProtocolA {}
class ClassB {
var someOptional: (ClassA & ProtocolA)? // here is optional value
var some: ClassA & ProtocolA // here is non-optional value; need to provide init though :)
}
One and probably a bit ugly one of the ways to do that, is to create a wrapper protocol for UIView:
protocol UIViewRef {
var instance: UIView { get }
}
Now it is possible to create a protocol which implements Protocol1, Protocol2 and UIViewRef, which is going to be used to get the UIView itself:
protocol MyUIViewProtocol: UIViewRef, Protocol1, Protocol2 { }
And last step will be implementing UIViewRef protocols for your UIViews, which, in you case, as I understand, already implement Protocol1 and Protocol2:
// SomeOfMyViews already implements Protocol1 and Protocol2
extension SomeOfMyUIViews: MyUIViewProtocol {
var instance: UIView { return self }
}
As the result we have MyUIViewProtocol, implementers of which hold a reference to a UIView and each of them implement
Protocol1 and Protocol2. One caveat though - to get the UIView itself, we need to ask it's reference from instance
property. For example
// Lets say we're somewhere in a UIViewController
var views: [SomeOfMyUIView] = // Get list of my views
views.forEach { self.view.addSubview($0.instance) }