Swift conform to protocol subclass
Change
public protocol Restorable: AnyObject {
var storyItem: StoryItem? { get set } // adopter must declare as StoryItem
}
to
public protocol Restorable: AnyObject {
associatedtype T : StoryItem
var storyItem: T? { get set } // adopter must declare as StoryItem adopter
}
Now your code compiles. Full example:
public protocol StoryItem {
var id: Int64? { get }
}
public protocol Restorable: AnyObject {
associatedtype T : StoryItem
var storyItem: T? { get set }
}
public struct TextItem: StoryItem {
public var id: Int64?
public var text: String?
}
class ResizableLabel: UILabel, Restorable {
var storyItem: TextItem? // ok because TextItem is a StoryItem adopter
}
How to conform to protocol using subclass
You could use an associatedType
that is constrained to be of type UIView
.
protocol A: class {
associatedtype View: UIView
func configure(view: View)
}
Now in class B
, since UILabel
is a subclass of UIView
, it's fine to do:
final class B: A {
init() {}
func configure(view: UILabel) {
...
}
}
Need to satisfy Swift protocol requirement by using a specific subclass of the requirement (or type that conforms to it)
To conform to protocol A, Model2
would need a member var a
that allows storing a reference to anything conforming to protocol A, not just a reference to a Model1
. So you can't do this.
Swift Protocol - Property type subclass
The problem is with the setter in the protocol.
Let's say you want to GET the panelView
from LeftPanelController
. That's fine, because LeftPanelView
can do everything PanelView
can do (and more).
If you want to SET the panelView
of LeftPanelController
though, you can give it any PanelView
. Because you're defining the panelView
variable as a LeftPanelView
, the setter could sometimes fail.
To fix this, you could do the following in LeftPanelController
:
var panelView: PanelView = LeftPanelView()
The implication of this is that you won't be able to access any methods or properties that are specific to LeftPanelView
without casting it first. If that's not an issue, then this should fix your problem!
Swift protocol conformance requirements for subtypes
When you define a variable in a protocol and assign a type to it, that is going to be a concrete type, so you cannot change it to a subclass of that type when conforming to the protocol. The type of the variable declared in the conforming class must be the same type as declared in the protocol, it cannot be a covariant (inheritance related) type.
You can fix the second error by creating an associatedType
for your Observer
protocol, which inherits from ObserverObject
then you can define object
to be of the same type as your associated type. Then you can make your ObserverClass
have a property object
of type ObservedObjectSubclass
.
class ObservedObject {}
class ObservedObjectSubclass: ObservedObject {}
protocol Observer {
associatedtype ObjectSubclass: ObservedObject
var object:ObjectSubclass { get }
}
class ObserverClass: Observer {
var object = ObservedObjectSubclass()
}
How to override swift protocol functions for subclasses (e.g. UILabel from UIView)
You can achieve that as below, You just need to expose aProtocol
to Objective-c
runtime for overriding
its methods in the extension
.
@objc protocol aProtocol {
typealias completionBlock = (_ finished:Bool)->()
func doSomething(completion: completionBlock)
}
extension UIView: aProtocol {
func doSomething(completion: (Bool) -> ()) {
print("Im an UIView")
}
}
extension UILabel {
override func doSomething(completion: (Bool) -> ()) {
// you can call super.doSomething(completion: completion)
print("im an UILabel")
}
}
extension UIImageView {
override func doSomething(completion: (Bool) -> ()) {
// you can call super.doSomething(completion: completion)
print("im an UIImageView")
}
}
Output:
Im an UIView
Im an UIView
im an UILabel
im an UIImageView
Swift: How can I make a function with a Subclass return type conform to a protocol, where a Superclass is defined as a return type?
Before you go much further, I'd recommend some background reading on covariance vs contravariance and the Liskov substitution principle.
Return types for methods overridden when subclassing are covariant: the subclass override of a method can return a subtype of the superclass method's return type.
Generic type parameters are invariant: a specialization can neither narrow nor expand the type requirements.
The relationship between a protocol and a concrete type that adopts it is more like generics than like subclassing, so return types declared in protocols are invariant, too. (It's hard to say exactly why on first read. Possibly something about existential vs constraint-only protocols?)
You can allow covariance in a protocol by specifying associated type requirements, though:
protocol SomeProtocol {
associatedtype ReturnType: SuperclassType
func someFunction(someParameter: SomeType) -> ReturnType
}
class SomeClass : SomeProtocol {
func someFunction(someParameter: SomeType) -> SubclassType { /*...*/ }
}
Now, it's clear that the return type of someFunction
in a type adopting SomeProtocol
must be either SuperclassType
or a subtype thereof.
How is Self in protocol interpreted in subclass?
According to the documentation Self in this case will be A since A is the one conforming to the protocol, B is only doing it indirectly as a subclass of A.
So when A conforms to Copyable
you are saying that A and all its subclasses must have an init(_ instance: A)
In a protocol declaration or a protocol member declaration, the Self type refers to the eventual type that conforms to the protocol.
You can actually test this by removing the required init(_ instance: A)
init and you will get an error even if you have an init(_ instance: B)
, so since A is the class conforming to the protocol you must have an init where the instance
argument is A
Related Topics
Gmsmapview Animatetocameraposition Zoom in - Zoom Out Animation
iOS Swift Flood Fill Algorithm
Ios: How to Create Expandable Tableview in Swift Without Using Third Party Libraries or Pods
How to Catch Accessibility Focus Changed
Get Light or Dark Variant of a Color Declared in Assets
Cannot Invoke 'Decode' with an Argument List of Type '(T, From: Data)'
Swift 2 - Separating an Array into a Dictionary with Keys from a to Z
Swift - Nsdate and Last Week of Year
Uitableviewcell with Intrinsic Height Based on Width
How to Download and View Images from the New Firebase Storage
Cannot Access Appdelegate While Testing Xcode Project
How to Update a Swiftui View State from Outside (Uiviewcontroller for Example)
How to Convert Bytes to Half-Floats in Swift
Exc_Breakpoint (Sigtrap) on Production Version Only
Swift3 - How to Protect Secret Key
Uitabbar Transition Issue Below iOS 11 Swift