How can I explicitly implement a protocol in swift? If it is impossible, why?
Protocol extensions basically already do what you're describing:
protocol Cat {
}
extension Cat {
func quack() {
print("meow")
}
}
class Duck : Cat {
func quack() {
print("quack")
}
}
let d = Duck()
d.quack() // quack
(d as Cat).quack() // meow
How to implement a Swift protocol across structs with conflicting property names
The desired feature from explicit interface implementations is that they are statically dispatched, right? If you use Description
on a BusStop
, it will be an optional string, but if you use Description
on a Stop
, it will be a non-optional string.
In Swift, extension members are statically dispatched, so you can make use of this to achieve something similar:
extension Stop where Self == BusStop {
// Since the type of "self" here is BusStop, "Description" refers to the one declared in BusStop
// not this one here, so this won't cause infinite recursion
var Description : String { return self.Description ?? "" }
}
extension Stop where Self == TrainStop {
var Latitude: Double { return self.Latitude ?? 0 }
var Longitude: Double { return self.Longitude ?? 0 }
}
This code shows that this works:
let busStop = BusStop(Code: "ABC", Description: "My Bus Stop", Latitude: 0, Longitude: 0)
print(type(of: busStop.Description)) // Optional<String>
let stop: Stop = busStop
print(type(of: stop.Description)) // String
However, I still don't think this is good Swift code. It is often bad to just directly translate an API from one language to another. If I were you, I would make Longitude
, Latitude
and Description
in Stop
to be all optionals.
Is it possible for a class to explicitly invoke a method on a protocol's extension?
The following answer in the thread
- Calling protocol default implementation from regular method
describes using a nested dummy type to access the default implementation of a protocol from within a type that already has supplied its own implementation of that blueprinted method. We may extend this method to also allow actually making use of (blueprinted) properties of the MyClass2
instance, but within the call to the default implementation which MyClass2
already implements its custom version of (hence taking precedence over the default one).
We start by looking at a slightly more light weight version of your example, with a default implementation supplied for someFuncWithDefaultImplementation()
protocol MyProtocol : class {
func someFuncWithDefaultImplementation()
var someInt: Int { get set }
}
extension MyProtocol {
func someFuncWithDefaultImplementation() {
print("Called default impl. Currently, someInt = \(someInt)")
print("Mutates someInt from within default implementation (0) ...")
someInt = 0
}
}
We use the non-elegant nested type solution in the custom implementation of someFuncWithDefaultImplementation()
of MyClass2
, to call the default implementation of the latter, but stores a reference in the Dummy
instance back to the MyClass2
instance, to allow the someInt
property of MyClass2
to be used in the default implementation call (for reading and writing), even if this is called from the Dummy
type.
class MyClass2 : MyProtocol
{
var someInt: Int = 42
func someFuncWithDefaultImplementation()
{
// do some additional stuff ...
print("In MyClass2 implementation, currently someInt = \(someInt)")
/* Dummy 'MyClass2'-capturing type used to call the default
implementation of 'MyProtocol', but with read and write
access to 'MyClass2':s self:s 'someInt' instance. */
class Dummy : MyProtocol {
unowned let myClass2: MyClass2
init(_ myClass2: MyClass2) { self.myClass2 = myClass2 }
var someInt: Int {
get { return myClass2.someInt }
set { myClass2.someInt = newValue }
}
}
// call default implementation of 'someFuncWithDefaultImplementation'
// supplying 'self' to read/write access to self.someInt.
Dummy(self).someFuncWithDefaultImplementation()
print("Back in MyClass2:s implementation; now someInt = \(someInt)")
// 0, woah, mutated in default implementation!
}
}
let a = MyClass2()
a.someFuncWithDefaultImplementation()
/* In MyClass2 implementation, currently someInt = 42
Called default impl. Currently, someInt = 42
Mutates someInt from within default implementation (0) ...
Back in MyClass2:s implementation; now someInt = 0 */
You could also choose to declare the nested Dummy
outside of the function, just marking it private
to make sure it cannot be accessed from outside MyClass2
:
class MyClass2 : MyProtocol
{
var someInt: Int = 42
/* Dummy 'MyClass2'-capturing type used to call the default
implementation of 'MyProtocol', but with read and write
access to 'MyClass2':s self:s 'someInt' instance. */
private class Dummy : MyProtocol {
unowned let myClass2: MyClass2
init(_ myClass2: MyClass2) { self.myClass2 = myClass2 }
var someInt: Int {
get { return myClass2.someInt }
set { myClass2.someInt = newValue }
}
}
func someFuncWithDefaultImplementation()
{
// do some additional stuff ...
print("In MyClass2 implementation, currently someInt = \(someInt)")
// call default implementation of 'someFuncWithDefaultImplementation'
// supplying 'self' to read/write access to self.someInt.
Dummy(self).someFuncWithDefaultImplementation()
print("Back in MyClass2:s implementation; now someInt = \(someInt)")
// 0, woah, mutated in default implementation!
}
}
I will, however, repeat the same as the author of the linked answer: this approach is not very elegant.
Swift 2.0: Protocol extensions: Two protocols with the same function signature compile error
A protocol defines requirements (methods, properties, ...) for a
conformant type.
protocol FirstDelegate {
func someFunc()
}
protocol SecondDelegate {
func someFunc()
}
defines two protocols with the same required method someFunc()
.
A conformant type must implement this method:
class SomeClass: FirstDelegate, SecondDelegate {
func someFunc() {
print("SomeClass implementation")
}
}
A protocol extension provides method and property implementations
to conformant types. A special case of a protocol extension is a
default implementation, which is what you defined here:
extension FirstDelegate {
func someFunc() {
print("First delegate")
}
}
It defines a default implementation of someFunc()
for all types
conforming to FirstDelegate
. Since this is the only required
method of that protocol, a conforming class need not define the
method at all:
class SomeClass: FirstDelegate {
}
SomeClass().someFunc() // Output: First delegate
But if the class provides its own implementation then that
will be used:
class SomeClass: FirstDelegate {
func someFunc() {
print("SomeClass implementation")
}
}
SomeClass().someFunc() // Output: SomeClass implementation
In your case, you have defined default implementations of someFunc()
for both protocols:
extension FirstDelegate {
func someFunc() {
print("First delegate")
}
}
extension SecondDelegate {
func someFunc() {
print("Second delegate")
}
}
A class can still conform to both protocols if it provides its own
implementation of the required method:
class SomeClass: FirstDelegate, SecondDelegate {
func someFunc() {
print("SomeClass implementation")
}
}
But the class cannot conform by using the default implementation
class SomeClass: FirstDelegate, SecondDelegate {
}
for both protocols
because there is a conflict. It is unspecified which default
implementation should be used, and that's why the compiler complains.
Actually the class now conforms to none of the protocols.
This can be seen in the full compiler log in the Report navigator:
main.swift:24:7: error: type 'SomeClass' does not conform to protocol 'FirstDelegate'
class SomeClass: FirstDelegate, SecondDelegate {
^
main.swift:5:10: note: multiple matching functions named 'someFunc()' with type '() -> ()'
func someFunc()
^
main.swift:19:10: note: candidate exactly matches
func someFunc() {
^
main.swift:13:10: note: candidate exactly matches
func someFunc() {
^
main.swift:24:7: error: type 'SomeClass' does not conform to protocol 'SecondDelegate'
class SomeClass: FirstDelegate, SecondDelegate {
^
main.swift:9:10: note: multiple matching functions named 'someFunc()' with type '() -> ()'
func someFunc()
^
main.swift:19:10: note: candidate exactly matches
func someFunc() {
^
main.swift:13:10: note: candidate exactly matches
func someFunc() {
^
implement protocol with different associated type
I just fund a way to archive this. The trick is to add another associated type in one of the subtypes of the protocol:
protocol ConvertableInt : Convertable {
associatedtype TResI
typealias TargetType = TResI
}
extension MyData : Convertable {
typealias TargetType = String
func convert() -> String { return String(self.data) }
}
extension MyData : ConvertableInt {
typealias TResI = Int
func convert() -> TResI { return self.data }
}
This also allows to get rid of the second subtype for string.
While this passes the compiler it totally crashes at runtime!
The compiler always calls the method defined which was defined at the explicit typealias
. In this case:
typealias TargetType = String
Which will result in interpreting the address as a integer and give you totally wrong results. If you define it vice versa it will simply crash because it tries to interpret the integer as a address.
Related Topics
Get the String Up to a Specific Character
Pod Install Gpuimage Does Not Work
Create Complicated Nscompoundpredicate in Swift 3
Skscene Becomes Unresponsive While Being Idle
Firebase Storage Overwriting Files
How to Connect Outlets and Actions in Swift/Macos Programaticly
How to Display Current Time (Realtime) in iOS 14 Home Widget
Moving Skspritenode to Location of the Touch
How to Declare Exponent/Power Operator with New Precedencegroup in Swift 3
Swift 4.2, String Firstindex() Function Error in Xcode Playground
Can You Enforce a Typealias in Swift
Instance Member 'View' Cannot Be Used on Type 'Gamescene'
Making Button Span Across VStack
Swiftui [Bug] Navigationview and List Not Showing on iPad Simulator Only