Swift: overriding typealias inside subclass
Unfortunately there is no good workaround for this problem.
The main idea to override the typealias
would work in this case but consider the following:
protocol TakeAndGet {
typealias T
func take(value: T)
func get() -> T
}
class FirstClass: TakeAndGet {
typealias T = FirstClass
var property = 0
func take(value: T) {
value.property = 4
}
func get() -> T {
return FirstClass()
}
}
class SecondClass: FirstClass {
typealias T = SecondClass
var property2 = "hello"
}
If the typealias
of the SecondClass
overrides the other one the take
method would work since it takes a subclass which can be treated as the superclass. But the get
method cannot implicitly convert FirstClass
to SecondClass
. Therefore it is not possible to override a typealias
.
Now if we want to override the get
function with get() -> SecondClass
it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get
method which results in an ambiguous use:
SecondClass().get() // which type gets returned? SecondClass or FirstClass
So you have to try a different approach.
Swift: override associatedtype from protocol extension in protocol conformance
I have created the same code. There are some facts that need to be understood here.
extension MyProtocol {
typealias ResponseType = MyDefaultDecodableType
func handleResponse(data: Data) -> ResponseType {
return try! JSONDecoder().decode(MyDefaultDecodableType.self, from: data)
}
}
Conceptually, there are no generic protocols in Swift. But by using typealias
we can declare a required alias for another type.
Your extension doesn't need to define typealias ResponseType = MyDefaultDecodableType
as it is going to provide some default implementation using MyDefaultDecodableType
, so it is useless.
So your extension would be something like this
extension MyProtocol {
// typealias ResponseType = MyDefaultDecodableType // NO NEED FOR IT
func handleResponse(data: Data) -> MyDefaultDecodableType {
print("Test \(self)")
return try! JSONDecoder().decode(MyDefaultDecodableType.self, from: data)
}
}
Now you can define
class MyObject:MyProtocol {
typealias ResponseType = AnotherDecodableType
func handleResponse(data: Data) -> ResponseType {
print("Test \(self)")
return try! JSONDecoder().decode(AnotherDecodableType.self, from: data)
}
}
class MyObject2:MyProtocol {
}
Without any errors
Now if you use
MyObject().handleResponse(data:data)
MyObject2().handleResponse(data:data2)
You will get
test __lldb_expr_44.MyObject
test __lldb_expr_44.MyObject2
Use of typealias syntax within protocols in the Swift standard library
Take a look at this answer. Use of a colon shows inheritance, use of an equals sign shows assignment.
In my understanding this means the following:
typealias X // defines associated type X for subclasses to override
typealias X: Y // defines associated type X and requires that it conform to Y
typealias X = Z // defines associated type X with a default of type Z
typealias X: Y = Z // defines associated type X with a default of type Z and requires that any overrides conform to Y
My interpretation seems to be supported by this article on Swift generics:
An associated type is declared by a protocol using the typealias
keyword. It normally set by an item that conforms to that protocol,
although you can supply a default. Like type parameters, an
associated type can be used as a token when building generic type
rules.
The use of the keyword typealias
can be misleading for defining associated types and may be replaced by associatedtype
in the future.
Can my class override protocol property type in Swift?
Requiring AnyObject in the protocol means the children
array must be able to accept AnyObject
entries. But it sounds like you want Bar
's children to be only Foo
objects.
Instead, you can give the protocol an associated type:
protocol Parent {
associatedtype Child
var children: [Child] { get set }
}
class Foo { }
class Bar: Parent {
var children = [Foo]()
init() {}
}
Swift: Overriding == in subclass results invocation of == in superclass only
The reason the equality for A
is being invoked for an Array<A>
that contains B
is that overloading of free functions is resolved statically, not dynamically – that is, at compile time based on the type, not at runtime based on the pointed-to value.
This is not surprising given ==
is not declared inside the class and then overridden in the subclass. This might seem very limiting but honestly, defining polymorphic equality using traditional OO techniques is extremely (and deceptively) difficult. See this link and this paper for more info.
The naïve solution might be to define a dynamically dispatched function in A
, then define ==
to just call that:
class A: Equatable {
func equalTo(rhs: A) -> Bool {
// whatever equality means for two As
}
}
func ==(lhs: A, rhs: A) -> Bool {
return lhs.equalTo(rhs)
}
Then when you implement B
, you’d override equalTo
:
class B: A {
override func equalTo(rhs: A) -> Bool {
return (rhs as? B).map { b in
return // whatever it means for two Bs to be equal
} ?? false // false, assuming a B and an A can’t be Equal
}
}
You still have to do one as?
dance, because you need to determine if the right-hand argument is a B
(if equalTo
took a B
directly, it wouldn’t be a legitimate override).
There’s also still some possibly surprising behaviour hidden in here:
let x: [A] = [B()]
let y: [A] = [A()]
// this runs B’s equalTo
x == y
// this runs A’s equalTo
y == x
That is, the order of the arguments changes the behaviour. This is not good – people expect equality to be symmetric. So really you’d need some of the techniques described in the links above to solve this properly.
At which point you might feel like all this is getting a bit unnecessary. And it probably is, especially given the following comment in the documentation for Equatable
in the Swift standard library:
Equality implies substitutability. When
x == y
,x
andy
are interchangeable in any code that only depends on their values.Class instance identity as distinguished by triple-equals
===
is
notably not part of an instance's value. Exposing other non-value
aspects ofEquatable
types is discouraged, and any that are
exposed should be explicitly pointed out in documentation.
Given this, you might seriously want to reconsider getting fancy with your Equatable
implementation, if the way you’re implementing equality is not in a way where you’d be happy with two values being equal being substituted with each other. One way to avoid this is to consider object identity to be the measure of equality, and implement ==
in terms of ===
, which only needs to be done once for the superclass. Alternatively, you could ask yourself, do you really need implementation inheritance? And if not, consider ditching it and using value types instead, and then using protocols and generics to capture the polymorphic behaviour you’re looking for.
PAT typealias is ambiguous for type lookup in this context
I want to make the method's implementation mandatory for any subclass
of AnyDataSource.
The way to express that is to make AnyDataSource
generic.
class AnyDataSource<Entity: EntityProtocol>: DataSourceProtocol {
func get() -> Entity { .init() }
}
class DataSource_A<Entity: EntityProtocol & DataSource_A_Compatible>: AnyDataSource<Entity> {
// override if needed
}
Swift - class method which must be overridden by subclass
You have two options:
1. Use a Protocol
Define the superclass as a Protocol instead of a Class
Pro: Compile time check for if each "subclass" (not an actual subclass) implements the required method(s)
Con: The "superclass" (protocol) cannot implement methods or properties
2. Assert in the super version of the method
Example:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
Pro: Can implement methods and properties in superclass
Con: No compile time check
Related Topics
Scenekit Physics Add Velocity in Local Space
Hide Status Bar in Launch Screen
How to Save a Generic Measurement<Unit> in Core Data
Type '()' Cannot Conform to 'View'
Accessing Nested Dictionary from API in Swift
Multidimensional Dictionaries Possible in Swift
How to Observe Array Property Changes in Rxswift
Swift Memory Management: Storing Func in Var
Alamofire 3 Custom Encoding to Alamofire 4 Custom Encoding
Swiftui Widget iOS 14 Gradient Issue
Swift Combine: Using Timer Publisher in an Observable Object
Need Help Converting (Cfpropertylistref *)Nsdictionary to Swift
How to Draw Two Polylines in Different Colors in Mapkit
Realmswift + Multiple Predicate
How to Create Public Extensions, in a Shared Framework, for Xctest