Assume there is a protocol Draggable
, usually will be conformed by an UIView
object
protocol Draggable {
drag()
}
We can either implement drag()
in a protocol extension as option 1
// option 1
extension Draggable where Self: UIView {
func drag() {
// implementation
}
}
extension UIView: Draggable {} // added after @Rich Tolley's answer
Or we can implement drag()
in a UIView
extension as option 2
// option 2
extension UIView: Draggable {
func drag() {
// implementation
}
}
And idea would be helpful.
Protocols let you describe what methods something should have, but don't provide the code inside. Extensions let you provide the code inside your methods, but only affect one data type – you can't add the method to lots of types at the same time.
You can create objects from classes, whereas protocols are just type definitions. Try to think of protocols as being abstract definitions, whereas classes and structs are real things you can create.
In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.
Swift Class Extensions Another way to add new functionality to a Swift class is to use an extension. Extensions can be used to add features such as methods, initializers, computed properties and subscripts to an existing class without the need to create and reference a subclass.
Yes, there is a difference: (EDIT: or at least there was in the original version of this q, which didn't add extension UIView : Draggable {}
to the end of option 1).
Option 1 creates a default implementation for instances of UIView
that conform to Draggable
. You still need to mark UIView
s you wish to conform to Draggable
as such in the declaration: class MyView : Draggable
. Anything that conforms to Draggable
but is not a UIView
subclass will need to supply its own implementation.
Option 2 extends all UIView
s to make them conform to Draggable
. Nothing else can be a Draggable
unless separate extensions are also written for those classes, or they are manually conformed to the protocol. There is no need to add Draggable
in the class declaration.
The protocol extension is usually the better option. In this case this is obviously true since not all UIView
s can be Draggable
. Also, going down the protocol extension route means that you can create a Draggable
object that is not a UIView
subclass, if necessary (admittedly fairly unlikely, since most Cocoa controls are UIView
subclasses - although not all -UIBarButtonItem
isn't, strangely)
If you follow option 2, you will be adding unnecessary methods to UIView
in a lot of cases, which is a violation of good object oriented design - specifically the Interface Segregation Principle (clients should not be forced to rely on methods they don't use
) - which is the 'I' in the SOLID principles
A protocol extension should be used when you want to implement functionality for more than just one class.
In this case you should use the extension UIView: Draggable
as the Implementation is specific to the UIView class.
Assuming you have a protocol which provides location:
protocol Location {
var location: CGPoint { get set }
}
and you want every class which implements Location to conform to Draggable, then a protocol extension could be used:
extension Draggable where Self: Location {
func drag() {
}
}
For further reference, you should have a look at Protocol-Oriented Programming in Swift from the 2015 WWDC.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With