Let's say that I have generic class Bus:
class Bus<T> {
func doSomething() {}
}
and I can create instance of it:
var myBus = Bus<String>()
Now I have a function that takes one parameter of the AnyObject
and tests it's type:
func checkType(object: AnyObject) {
if let foo = object as? String {
println("string")
}
}
My problem is that I can't see a way to check if object
is of type Bus
and run function doSomething()
if it is of type Bus
. Any help would be appreciated.
Edit: Protocols also don't seem to solve this the way they should.
import Foundation
@objc protocol BusProtocol {
func doSomething() -> Void
}
class Bus<T> : BusProtocol {
func doSomething() -> Void {
println("asdf")
}
}
func checkType(object: AnyObject) {
if let foo = object as? Bus<AnyObject> {
foo.doSomething() // no match
}
if let foo = object as? Bus<Any> {
foo.doSomething() // no match
}
if let foo = object as? Bus<String> {
foo.doSomething() // prints "asdf"
}
if let foo = object as? BusProtocol {
foo.doSomething() // SIGABRT -- -[SwiftObject doesNotRecognizeSelector:]
}
}
checkType(Bus<String>())
Checking TypeUse the type check operator ( is ) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it's not.
Type classes, also known as extension interfaces, are usually represented in Swift as protocols with associated types and/or Self requirements. They are groups of functions that operate on generic type parameters and are governed by algebraic laws.
Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.
The problem here is your thinking of Bus
as a concrete thing. It really isn't. Bus<String>
is. Bus<Int>
is too. But Bus
isn't, at least not in the same sense. You need to know what T
is.
Really, what you want is to write something like this:
func checkType<T>(object: AnyObject) {
if let foo = object as? Bus<T> {
println("Bus<T>")
}
}
But if you try and use it, you'll get an error:
// error: Argument for generic parameter 'T' could not be inferred.
checkType(myBus)
Unlike in other languages, you can't write checkType<String>(myBus)
. But the following might do what you're looking for:
func checkType<T>(object: AnyObject, T.Type) {
if let foo = object as? Bus<T> {
println("Bus<T>")
}
}
checkType(myBus,String.self)
This fixes what T
is for any Bus<T>
and will work correctly.
You might object that you don't want to specify what T
is. However, instead, this leads to the question... once you've figured out that object
is some kind of Bus
, what are you going to do then? Are you planning on calling methods on it, or passing it as an argument to other functions? Chances are what you're trying to achieve can be better done with a generic function and protocol constraints, rather than using AnyObject
and casting.
In swift 2.x you can use a protocol to achieve this, as you attempted without error:
protocol Busish {
func doSomething() -> Void
}
class Bus<T> : Busish {
func doSomething() {
print(self)
}
}
func with_any_bus(obj:AnyObject) {
if let b = obj as? Busish {
b.doSomething()
}
}
with_any_bus(Bus<Int>());
with_any_bus(Bus<String>());
output:
swiftblah.Bus<Swift.Int>
swiftblah.Bus<Swift.String>
This may or may not be helpful to you specifically, since you seem to be using 1.2, but maybe someone else who stumbles on this question will find it useful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With