Swift: Overriding Typealias Inside Subclass

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 and y
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 of Equatable 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



Leave a reply



Submit