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
}
}
Related
In Swift, I want to make my base class static method return its subclass objects when the static method is called from a subclass.
When returning one subclass object, I can make it possible by using init().
But when returning multiple subclass objects, init() can not be used.
And I want to not only just return subclass objects from the parent static method, but also to implement some logic other than instantiation in the parent static method, and make the static method of each subclass inherit the parent's static method behavior.
I have 3 sub-classes. So, I don't want to write the same code in the static methods of 3 sub-classes.
How should I do?
If possible, I want to use the static method instead of init() to return a single subclass object, too.
class Base {
func f() {
print("base class")
}
// this does not works. it creates a base class object.
static func createSubclassObject() -> Base {
return Base()
}
// this works. it creates a subclass object.
init() {
}
// this does not work. base class objects are created.
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
objects.append(Base())
}
return objects
}
/* probably I need something like this. but this code generates a compile error
static func createSubclassObjects(count: Int) -> [Self] {
var objects = [Self]()
for _ in 0 ..< count {
objects.append(Self())
}
return objects
}
*/
// generic also does not work. this returns a base class object.
static func createSubclassObjectByGeneric<T: Base>() -> T {
return T()
}
}
class Sub: Base {
override func f() {
print("sub class")
}
}
print(Sub().f())
// sub class・
print(Sub.createSubclassObject().f())
// base class
Sub.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
print(Sub.createSubclassObjectByGeneric().f())
// base class
You need to return Self, not Base.
static func createSubclassObject() -> Self {
.init()
}
required init() { }
Also, don't use a for loop. There is an array initializer premade for what you're doing.
static func createSubclassObjects(count: Int) -> [Base] {
.init(repeating: createSubclassObject(), count: count)
}
The following code works. But I think there should be better solutions because I don't want to define class func sub() in the parent class and override class func sub() in each sub class.
EDIT: See the Jessy's answer, which is the better solution.
class Base {
func f() {
print("base class")
}
static func createSubclassObjects(count: Int) -> [Base] {
var objects = [Base]()
for _ in 0 ..< count {
//objects.append(Base())
objects.append(Self.sub())
}
return objects
}
class func sub() -> Base {
Base()
// or use fatalError() if you don't need to call createSubclassObjects(count: Int) from the base class
}
}
class Sub1: Base {
override func f() {
print("sub1 class")
}
override class func sub() -> Base {
Sub1()
}
}
class Sub2: Base {
override func f() {
print("sub2 class")
}
override class func sub() -> Base {
Sub2()
}
}
Base.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// base class
// base class
Sub1.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub1 class
// sub1 class
Sub2.createSubclassObjects(count: 2).forEach {
print($0.f())
}
// sub2 class
// sub2 class
how can I correct errors?!
domain module, contains all abstracts
//MARK: - Domain
protocol TypeB {
associatedtype P
func makeP() -> P
init()
}
protocol TypeA {
associatedtype P
associatedtype B: TypeB
func makeP() -> P
init(objB: B)
}
protocol FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int
}
protocol SecondTargetFabricType {
func makeA<B, A: TypeA>(objcB: B) -> A where A.B == B, A.P == B.P, B.P == Int
}
the first module, for example the module for working with the network
//MARK: - First Target
class ClassB: TypeB {
required init() { }
func makeP() -> Double { return 10 }
}
// error: Cannot convert return expression of type 'ClassB' to return type 'B'
class FirstTargetFabric: FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int {
return ClassB()
}
}
the second module, for example the module for working with the storage
//MARK: - SecondTarget
class ClassA<B: TypeB>: TypeA {
let objB: B
required init(objB: B) {
self.objB = objB
}
func makeP() -> B.P { return objB.makeP() }
}
class SecondTargetFabric: SecondTargetFabricType {
func makeA<B, A: TypeA>(objcB: B) -> A where B == A.B, B.P == A.P, B.P == Int {
return A(objB: objcB)
}
}
application target
//MARK: - app
let firstFabric: FirstTargetFabricType = FirstTargetFabric()
let secondFabric: SecondTargetFabricType = SecondTargetFabric()
/// error: Generic parameter 'A' could not be inferred
let res = secondFabric.makeA(objcB: firstFabric.makeB())
I'm trying to make a service loader for pagination. I just want to pass in the class initializer an entity that will go to the network
how good would that approach be?
//MARK: - Domain
open class TypeB<T: Decodable> {
open func makeP() -> T {
fatalError("Required function have not been implemented")
}
}
open class TypeA<T: Decodable> {
open func makeP() -> T {
fatalError("Required function have not been implemented")
}
}
public protocol FirstTargetFabricType {
func makeInt() -> TypeB<Int>
func makeDouble() -> TypeB<Double>
}
public protocol SecondTargetFabricType {
func makeInt(objInt: TypeB<Int>) -> TypeA<Int>
func makeDouble(objDouble: TypeB<Double>) -> TypeA<Double>
}
//MARK: - First Target
internal class ClassB: TypeB<Int> {
override func makeP() -> Int { return 10 }
}
internal class ClassBB: TypeB<Double> {
override func makeP() -> Double { return 20 }
}
public class FirstTargetFabric: FirstTargetFabricType {
public func makeInt() -> TypeB<Int> { ClassB() }
public func makeDouble() -> TypeB<Double> { ClassBB() }
}
//MARK: - SecondTarget
internal class ClassA: TypeA<Int> {
let objB: TypeB<Int>
init(objB: TypeB<Int>) {
self.objB = objB
}
override func makeP() -> Int {
objB.makeP()
}
}
internal class ClassAA: TypeA<Double> {
let objB: TypeB<Double>
init(objB: TypeB<Double>) {
self.objB = objB
}
override func makeP() -> Double {
objB.makeP()
}
}
public class SecondTargetFabric: SecondTargetFabricType {
public func makeInt(objInt: TypeB<Int>) -> TypeA<Int> { ClassA(objB: objInt) }
public func makeDouble(objDouble: TypeB<Double>) -> TypeA<Double> { ClassAA(objB: objDouble) }
}
//MARK: - app
let first = FirstTargetFabric()
let second = SecondTargetFabric()
let objInt = first.makeInt()
let objDouble = first.makeDouble()
print(second.makeInt(objInt: objInt).makeP())
print(second.makeDouble(objDouble: objDouble).makeP())
This is the proper way of doing it with protocols, but that might become very complicated if you keep on going with associated protocols.
In method makeAa: you are trying to return TypeA as type A, and not all TypeA are A, so you have to return A instead
protocol TypeA {
associatedtype P
associatedtype B: TypeB
func makeP() -> P
init(objB: B)
}
protocol TypeB {
associatedtype P
func makeP() -> P
}
class ClassB: TypeB {
func makeP() -> Int { return 10 }
}
class ClassA<B: TypeB>: TypeA {
let objB: B
required init(objB: B) {
self.objB = objB
}
func makeP() -> B.P {
return objB.makeP()
}
}
//**Cannot convert return expression of type 'ClassA<B>' to return type 'A'**
func makeAa<B, A: TypeA>(objB: B) -> A where B.P == Int, A.P == B.P, A.B == B {
return A(objB: objB)
}
//**Generic parameter 'A' could not be inferred**
let res: ClassA = makeAa(objB: ClassB())
For the update:
Again, you have to return type B, not all ClassB are B()
// error: Cannot convert return expression of type 'ClassB' to return type 'B'
class FirstTargetFabric: FirstTargetFabricType {
func makeB<B: TypeB>() -> B where B.P == Int {
return B()
}
}
Here you have to specify generic class B that you want to create (ClassB)
/// error: Generic parameter 'A' could not be inferred
let b: ClassB = firstFabric.makeB()
let res: ClassA = secondFabric.makeA(objcB: b)
And ClassB should return the same (Int) as ClassA to combine them
//MARK: - First Target
class ClassB: TypeB {
required init() { }
func makeP() -> Int { return 10 }
}
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
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()
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)