0
votes

I have a protocol, conforming class and a class with one simple function.

protocol Outputable {
    static func output()
}

class Foo: Outputable {
    static func output() {
        print("output")
    }
}

class Bar {
    func eat(_ object: AnyObject?) {
        if let object = object, let objectType = type(of: object) as? Outputable.Type {
            objectType.output()
        }
    }
}

let foo = Foo()
let bar = Bar()
var fooOptional: Foo?
bar.eat(foo) // prints 'output'
bar.eat(fooOptional) // print nothing

Is there any way to pass some optional type being nil but conforming to Outputable protocol and call protocol's static functions inside eat function? Even though it's nil I am still passing a type and that's all I should need inside eat, right?

To make it more clear. I know why last line prints nothing. But is there a way to adjust eat to print that 'output' string out?

4

4 Answers

1
votes

One of the way you could achieve what you're seeking is to use generics and call your method on type:

func eat<T: Outputable>(_ object: T?) {
    T.output()
}

This will work for both Foo and Foo?

1
votes

You can extend Optional to conform to your protocol.

protocol Outputable {

    func output()

}

extension Optional: Outputable {

    func output() {
        switch self {
        case .some(let object):
            print("I have an object: \(object)")
        case .none:
            print("I'm nil")
        }
    }

}

class Foo { }

class Bar {

    func eat(_ object: AnyObject?) {
        if let object = object as? Outputable {
            object.output()
        }
    }

}

var foo: Foo?
let bar = Bar()
bar.eat(foo)  // prints "I'm nil"
0
votes

Put a break point at

if let object = object, let objectType = type(of: object) as? Outputable.Type {
    objectType.output()
}

You will realise that objectType.output() is not being called. if let succeeds in swift only if the right hand side object is not nil. Which is nil in your case.

0
votes

If you rewrite your test, the logic of why it's not working becomes clearer.

class Bar {
    func eat(_ object: AnyObject?) {
        if let object = object {
            if let objectType = type(of: object) as? Outputable.Type {
                objectType.output()
            } else {
                print("Mismatch on type")
            }
        } else {
            print("No object provided")
        }
    }
}

Shows:

  • output
  • No object provided