How to Declare a Variable That Has a Type and Implements a Protocol

How do I declare a variable that has a type and implements a protocol?

As of Swift 4, you can now do this.

Swift 4 implemented SE-0156 (Class and Subtype existentials).

The equivalent of this Objective-C syntax:

@property (strong, nonatomic) UIViewController<DetailViewController> * detailViewController;

Now looks like this in Swift 4:

var detailViewController: UIViewController & DetailViewController

Essentially you get to define one class that the variable conforms to, and N number of protocols it implements. See the linked document for more detailed information.

How to define variable that can be set and get in extension of protocol

The simplest way i think is define the variable in the protocol with the getter and setter. Then in your conform object you should declare the variable to conformance.
An Example:

protocol AbstractObject {

var maxProductCount: Int { get set }
}

struct ConformObject: AbstractObject {

var maxProductCount: Int
}

So now you can use your variable in your default implementations

extension AbstractObject {

mutating func addOne() -> Int {
self.maxProductCount += 1
return self.maxProductCount
}
}

In Swift, how can I declare a variable of a specific type that conforms to one or more protocols?

In Swift 4 it is now possible to declare a variable that is a subclass of a type and implements one or more protocols at the same time.

var myVariable: MyClass & MyProtocol & MySecondProtocol

To do an optional variable:

var myVariable: (MyClass & MyProtocol & MySecondProtocol)?

or as the parameter of a method:

func shakeEm(controls: [UIControl & Shakeable]) {}

Apple announced this at WWDC 2017 in Session 402: Whats new in Swift

Second, I want to talk about composing classes and protocols. So, here
I've introduced this shakable protocol for a UI element that can give
a little shake effect to draw attention to itself. And I've gone ahead
and extended some of the UIKit classes to actually provide this shake
functionality. And now I want to write something that seems simple. I
just want to write a function that takes a bunch of controls that are
shakable and shakes the ones that are enabled to draw attention to
them. What type can I write here in this array? It's actually
frustrating and tricky. So, I could try to use a UI control. But not
all UI controls are shakable in this game. I could try shakable, but
not all shakables are UI controls. And there's actually no good way to
represent this in Swift 3. Swift 4 introduces the notion of composing
a class with any number of protocols.

Define an object to be `Type` of a Class and to implement a protocol

You have two choices. You can either use a Generic with type constraints or use protocol extension with type constraints.

In the case of Generics it looks like:

protocol P1 {
}

class X {
}

class Y : X, P1 {
}


class Z<T: X,P1> {
var myProp : T?
}

In the case of protocol extensions, you can use the protocol to provide the required methods and properties and use the extension to implement them for the specific case when the protocol is implemented by the class (e.g. UIViewController). This may be a better option if you don't really need to require UIViewController, but it will be used in practice. I prefer this kind of design as it allows for looser coupling.

Specify a class that implements a protocol

Unfortunately it's imposible in Swift 2.2 and won't be added in Swift 3.0.
The idea that you want to create Type rule for types that inherit some class and implement protocol.

Image

So it's not very common that you will have such hierarchy and will have property where you want to store one of this classes.
Also in POP paradigm you should have additional protocol that give you properties that you need from UIView.


Maybe you have such usecase:
Sample Image

Then create additional class:
Sample Image

And your type will be P1Base


P.S. That's why if you create @property (nonatomic) UIViewController<UITableViewDelegate> *protocolClassProperty; in Obj-c, it will be bridged as UIViewController! in Swift

Declare a Swift protocol which has a property return value CollectionTypeInt?

Not as a nested protocol, but it's fairly straightforward using the type erasers (the "Any" structs).

protocol A {
var intCollection: AnyRandomAccessCollection<Int> { get }
}

This is actually often quite convenient for return values because the caller usually doesn't care so much about the actual type. You just have to throw a return AnyRandomAccessCollection(resultArray) at the end of your function and it all just works. Lots of stdlib now returns Any erasers. For the return value problem, it's almost always the way I recommend. It has the nice side effect of making A concrete, so it's much easier to work with.

If you want to keep the CollectionType, then you need to restrict it at the point that you create a function that needs it. For example:

protocol A {
typealias IntCollection: CollectionType
var intCollection: IntCollection { get }
}

extension A where IntCollection.Generator.Element == Int {
func sum() -> Int {
return intCollection.reduce(0, combine: +)
}
}

This isn't ideal, since it means you can have A with the wrong kind of collection type. They just won't have a sum method. You also will find yourself repeating that "where IntCollection.Generator.Element == Int" in a surprising number of places.

In my experience, it is seldom worth this effort, and you quickly come back to Arrays (which are the dominant CollectionType anyway). But when you need it, these are the two major approaches. That's the best we have today.



Related Topics



Leave a reply



Submit