Overriding the method - unexpected behaviour - swift

I have code like this:
class A {
func method() { print("method from A") }
}
class B: A {
override func method() { print("method from B") }
}
class C: A {
override func method() { print("method from C") }
}
func run (_ obj: A) {
doIt(obj)
}
func doIt(_ obj: A) {
print("specific logic when object of A class")
obj.method()
}
func doIt(_ obj: B) {
print("specific logic when object of B class")
obj.method()
}
func doIt(_ obj: C) {
print("specific logic when object of C class")
obj.method()
}
let obj = C()
run(obj)
I am getting output:
specific logic when object of A class method from C
but i would expect:
specific logic when object of C class method from C
How should I change the code to get this behavior?

The problem is merely that you have made doIt three loose functions. Instead, make it three methods of the three classes:
class A {
func method() { print("method from A") }
func doIt() {
print("specific logic when object of A class")
self.method()
}
}
class B: A {
override func method() { print("method from B") }
override func doIt() {
print("specific logic when object of B class")
self.method()
}
}
class C: A {
override func method() { print("method from C") }
override func doIt() {
print("specific logic when object of C class")
self.method()
}
}
func run (_ obj: A) {
obj.doIt()
}
Now polymorphism does the work for you.

Although polymorphism is the best approach, here is another way you can do it
class A {
func method() { print("method from A") }
}
class B: A {
override func method() { print("method from B") }
}
class C: A {
override func method() { print("method from C") }
}
func run<T: A>(_ obj: T) {
doIt(obj)
}
func doIt<T: A>(_ obj: T) {
print("specific logic when object of \(T.self) class")
obj.method()
}
let obj = C()
run(obj)

Related

overriding declarations in extensions is not supported - swift

I made a minimal reproducible code of my issue.
enum Animal {
case cat
case dog
}
protocol AdoptPet {
func petIs(pet: Animal)
}
class Delegate {
}
extension Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
}
extension Girl {
override func petIs(pet: Animal) { // overriding declarations in extensions is not supported
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adpoter: Delegate){
let pet: Animal = .cat
adpoter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adpoter: Girl = Girl()
petCenter.setup(adpoter: adpoter)
What should I change in the code to make this compile ?
You need to move both the declaration of the function and the override into the type declarations from extensions. So Delegate needs to contain the petIs implementation in its declaration and Girl needs to override the petIs function in its body as well (using the override keyword) rather than in an extension.
class Delegate: AdoptPet {
func petIs(pet: Animal) {
print("not implemeted")
}
}
class Girl: Delegate {
override func petIs(pet: Animal) {
print(pet)
}
}
class PetCenter {
init () {
}
func setup(adopter: Delegate){
let pet: Animal = .cat
adopter.petIs(pet: pet)
}
}
let petCenter = PetCenter()
let adopter = Girl()
petCenter.setup(adopter: adopter) // cat

Override object method using Swift protocols and extensions

I would like to override a method that is declared in a framework and implemented in an extension.
Here's what I've tried :
import UIKit
// Code from a dependency
class Object { // UIViewController
func printSomething() {
print("something")
}
}
// My code
protocol SayHelloProtocol {
func hello()
func name() -> String
}
extension SayHelloProtocol {
func hello() {
print("Hello " + name())
}
func name() -> String {
"someone"
}
}
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
}
class MyHelloChildObject: MyHelloObject {
func name() -> String {
"You"
}
}
MyHelloObject().printSomething()
MyHelloChildObject().printSomething()
This will print :
Hello someone
Hello someone
But I would like to override the method so it prints :
Hello someone
Hello You
Is it possible to override a method implemented in an extension ?
It works if you add the name() function also to MyHelloObject:
class MyHelloObject: Object, SayHelloProtocol {
override func printSomething() {
hello()
}
func name() -> String {
"Someone"
}
}
class MyHelloChildObject: MyHelloObject {
override func name() -> String {
"You"
}
}

Apple way in Swift instead of an override?

what approach does Apple use in Swift instead of override, how can I write this without using the #objc marker
import Foundation
class A {
init() {}
}
extension A {
#objc func foo() {
print("foo")
}
}
class B: A {
override func foo() {
print("yes2")
}
}
A().foo()
B().foo()
maybe protocols? but how?
You can define a protocol and provide a default method implementation. Then all you need is to comform to that protocol and provide its own foo method if necessary:
protocol Fooable {
func foo()
}
extension Fooable {
func foo() {
print("default implementation")
}
}
class A: Fooable { }
class B: A {
func foo() {
print("B implementationn")
}
}
let a = A()
let b = B()
a.foo()
b.foo()
This will print
default implementation
B implementationn

Swift, derived classes with same named static function

I want to have the same named static function for multiple classes which are derived from each other. I really don't feel like naming them G_something, H_something, etc.
Is there any way in swift to do this:
class G {
static func dosomething()
{
print("G")
}
}
class H : G {
class func dosomething()
{
G.dosomething()
print("H")
}
}
class I : H {
class func dosomething()
{
H.dosomething()
print("I")
}
}
I.dosomething()
To be short :
class G {
class func dosomething()
{
print("G")
}
}
class H : G {
override class func dosomething()
{
super.dosomething()
print("H")
}
}
class I : H {
override class func dosomething()
{
super.dosomething()
print("I")
}
}
I.dosomething()
G
H
I
Simple overriding should works:
class G {
class func dosomething()
{
print("G")
}
}
class H : G {
override class func dosomething()
{
super.dosomething()
print("H")
}
}
class I : H {
override class func dosomething()
{
super.dosomething()
print("I")
}
}
I.dosomething()

Swift Inheritance: Super's Super

Supposing to have this three classes with this simply hierarchy:
class A {
func foo() {
print("A")
}
}
class B: A {
override func foo() {
super.foo()
print("B")
}
}
class C: B {
override func foo() {
// *******
print("C")
}
}
In class C, in overrided method foo I want to call a method foo: is it possible?
In C++ this can be achieved with C->A::foo(), but how do I do this in Swift?
super.foo() should be sufficient, since B prints "B" and calls super to print "A".
class C: B {
override func foo() {
super.foo()
print("C")
}
}
let c = C()
c.foo()
Output:
A
B
C
If you want to intentionally expose A's foo() from B, you need to create a new accessor:
class B: A {
override func foo() {
super.foo()
print("B")
}
func exposeFoo() {
super.foo()
}
}
class C: B {
override func foo() {
super.exposeFoo()
print("C")
}
}
Or, use NSObject and the power of the Objective-C runtime:
class A: NSObject { // make sure your base class inherits from NSObject
func foo() {
print("A")
}
}
// ...
class C: B {
override func foo() {
guard let superSuper = self.superclass?.superclass() else {
return; // no super super
}
let fooImp = class_getMethodImplementation(superSuper, "foo")
typealias MyCFunction = #convention(c) (AnyObject, Selector) -> Void
let curriedImplementation = unsafeBitCast(fooImp, MyCFunction.self)
curriedImplementation(self, selector) // prints A
}
}