2015-02-23 3 views
5

Допустим, что у меня есть общий класс Bus:Проверьте AnyObject имеет общего типа в Swift

class Bus<T> { 
    func doSomething() {} 
} 

и я могу создать экземпляр этого:

var myBus = Bus<String>() 

Теперь у меня есть функция который принимает один параметр AnyObject и испытывает его тип:

func checkType(object: AnyObject) { 
    if let foo = object as? String { 
     println("string") 
    } 
} 

Моя проблема заключается в том, что я не вижу способа проверить, имеет ли object тип Bus и выполняет функцию doSomething(), если он имеет тип Bus. Любая помощь будет оценена по достоинству.


Edit: протоколы также не кажется, решить эту, как они должны.

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>()) 
+1

Ваш пример редактирования с использованием '@ objc' не отображается в Segfault с помощью Swift 1.2 - но он дает вам ошибку (которая, предположительно, была проблема до этого, обрабатывается менее изящно), что методы в родовых классах не могут быть' @ objc' (потому что Objective-C не поддерживает дженерики). Однако, если вы отбросите классификатор '@ objc' в протоколе, он будет работать так же надежен (опять же, используя Swift 1.2, в котором появилось больше возможностей вокруг протоколов и' as') –

ответ

0

У вас его практически нет.

func checkType(object: AnyObject) { 
    if let foo = object as? Bus<AnyObject> { 
     print("Got here") 
    } else { 
     print("Fail") 
    } 
} 

let bus = Bus<String>() 
checkType(bus) // Fail 

let otherBus = Bus<AnyObject>() 
checkType(otherBus) // "Got Here" 

Я знаю, что это действительно не то, что вы хотите, но оно показывает, что нужно Быстро.

+0

Это не работает, я попробовал. Он бросает «Аргумент для родового типа« Т »не может быть выведен» –

+0

О, я понимаю, о чем вы сейчас спрашиваете. Вы должны знать, что находится на самом автобусе? Вам небезразличен тип автобуса? – jervine10

+1

Мне просто нужно проверить, является ли объект какой-то «шиной», и иметь возможность запускать 'doSomething()', если это так. –

6

Проблема в том, что вы думаете о Bus как о конкретной вещи. Это действительно не так. Bus<String> есть. Bus<Int> тоже. Но Bus нет, по крайней мере, не в том же смысле. Вы должны знать, что такое T.

Действительно, то, что вы хотите, чтобы написать что-то вроде этого:

func checkType<T>(object: AnyObject) { 
    if let foo = object as? Bus<T> { 
     println("Bus<T>") 
    } 
} 

Но если вы пытаетесь использовать его, вы получите сообщение об ошибке:

// error: Argument for generic parameter 'T' could not be inferred. 
checkType(myBus) 

В отличие от других языков, вы не можете написать checkType<String>(myBus). Но в следующем может делать то, что вы ищете:

func checkType<T>(object: AnyObject, T.Type) { 
    if let foo = object as? Bus<T> { 
     println("Bus<T>") 
    } 
} 

checkType(myBus,String.self) 

Это фиксирует, что T для любого Bus<T> и будет работать правильно.

Вы можете возразить, что не хотите указывать, что такое T. Однако вместо этого это приводит к вопросу ... как только вы выяснили, что object - это своего рода Bus, что вы собираетесь делать? Вы планируете называть методы на нем или передавать его в качестве аргумента для других функций? Скорее всего, то, чего вы пытаетесь достичь, может быть лучше сделано с общей функцией и ограничениями протокола, а не с использованием AnyObject и литья.

2

В быстром 2.х можно использовать протокол для достижения этой цели, как вы пытались без ошибок:

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>()); 

выход:

swiftblah.Bus<Swift.Int> 
swiftblah.Bus<Swift.String> 

Это может или не может быть полезным для вас специально, так как вы, кажется, использует 1.2 , но, возможно, кто-то другой, кто споткнется на этот вопрос, посчитает это полезным.

+0

Спасибо за это предложение. Я смог написать пустой протокол для проверки, был ли класс моим универсальным классом. Нет функциональности, я просто хотел проверить. –

Смежные вопросы