2016-12-26 4 views
-1

ジェネリックタイプがプロトコルに準拠しているかどうかを確認したいと思います。そうであれば、型自体をキャストし、それに対して静的メソッドを呼び出す必要があります。Swiftのタイプキャスト3

func log<T>(object: T) { 
    if let C = T as? Loggable { // this line doesn't compile 
     print("\(C.description(of: object))") 
    } else { 
     print("\(object)") 
    } 
} 

誰でも知っているのですか?

UPDATE

私は私の最初のコードスニペットであなたを混同しました。うまくいけば、秒はより意味をなさない。私は@ portellaの答えのおかげでいくつかの変更を加えましたが、まだ十分ではありません。あなたが関数に送信されたすべてのオブジェクトが私にとっては、私はこれが好きではないLoggable

プロトコルに準拠していることを確認し

protocol Loggable { 
    func log() 
    static func staticLog() 
} 

func log<L: Loggable>(object: L) { 
    object.log() 
    L.staticLog() 
} 

、しかし:

func decodeObject<T>() -> T? { 
    guard let object = objects.first else { 
     return nil 
    } 
    objects.removeFirst() 

    if object is NSNull { 
     return nil 
    } 

    if T.self is Coding.Type { // the condition is fixed, thanks to @Hiron 
     if let data = object as? Data { 
      return type(of: (T.self as! Coding)).from(data: data) as? T 
     } else { 
      return nil 
     } 
    } 

    return object as? T 
} 
+0

はなぜちょうど 'log'の2つのオーバーロードを持っていない(@Hironで述べた種類のチェックを使用しています) ? 1つは 'Loggable'の' T'で、もう1つは 'T'です。 – Hamish

+0

@Hamishこれはオプションかもしれません。答えが見つからない場合は、この方法で実装します。ありがとう –

+0

私は何とか[この回答](http://stackoverflow.com/questions/41236021/how-do-i-check-if-an-object-is-a-collection-swift/41237381#41237381)は、あなたは何をしようとしているのかに役立ちます。 –

答えて

0

if T.self is Coding.Type 

を書くべき

1

これはあなたのニーズに合うん以下の解決策が役立つことを願っています(私はを強くお勧めします)。

protocol Loggable { 
    func log() 
    static func staticLog() 
} 

func log<L>(object: L) { 
    guard let loggableObject = object as? Loggable else { 
     print(" Not a loggable object") 

     return 
    } 

    loggableObject.log() 
    type(of: loggableObject).staticLog() 
} 


final class NotLoggableClass {} 

final class LoggableClass: Loggable { 
    func log() { 
     print("") 
    } 

    static func staticLog() { 
     print("") 
    } 
} 

log(object: NotLoggableClass()) 

log(object: LoggableClass()) 

コールlog(object: NotLoggableClass())が返されます:Not a loggable object

を呼び出しlog(object: LoggableClass())が返されます:

EDIT:アップデートについては、引数の型や引数の型をチェックしたいですか?あなたはあなたの関数に引数を送信していませんが、それは奇妙に思えます。 私はあなたがそれを検証したいと思います。戻り値ではありません。 はあなたが達成しようとしている何これです:

protocol Coding { 
    associatedtype T 

    static func decodeObject<T>(data: Data) -> T? 
} 

extension UIImage: Coding { 
    typealias T = UIImage 

    static func decodeObject<T>(data: Data) -> T? { 
     return UIImage(data: data) as? T 
    } 
} 

あなたのソリューションについては、私はそれがどこから来たobjectsかを理解していません。 ジェネリック型がCoding に適合するようにするには、関数宣言の制約を使ってそれを行うことができます。

例:

protocol Coding { 
    associatedtype T 

    static func from(data: Data) -> T? 
} 

func decodeObject<T: Coding>(_ objects: [Data]) -> T? { 
    guard let object = objects.first else { 
     return nil 
    } 

    var objects = objects 
    objects.removeFirst() 

    return T.from(data: object) as? T 
} 

extension String: Coding { 
    static func from(data: Data) -> String? { 
     return String(data: data, encoding: .utf8) 
    } 
} 

私はあなたが何であるか私には思われる、これは型自体によってではなく、一般的なヘルパーか何かによって行うことに何かする必要があり、オブジェクトを理解していない、が、試してみる。

のは、あなたがプロトコルを持っているとしましょうたぶんあなたの代わりに

if T.self is Coding 
+0

ありがとうございます。あなたが言及したすべての点に同意します。とにかく、更新された質問をチェックしてください。 –

1

を助けることスウィフト

希望と動的キャストと型を避けるようにしてください静的メソッドとそれを実装するクラス:

protocol Something { 
    static func doSomething() 
} 

class SomethingConcrete: Something { 
    static func doSomething() { 
     // does something concrete 
    } 
} 

また、一般的な機能もあります。タイプがSomethingの場合、それは静的メソッドと呼ばれます(オブジェクトは関係ありません)。

これを行うには、オーバーロードとキャストという2つの方法があります。

(@portellaにクレジット)キャスティング

func someFunction<T: Something>() { 
    T.doSomething() 
} 

func someFunction<T>() { 
    // does something else 
} 

のオーバーロードは

func someFunction<T>() { 
    if T.self is Something.Type { 
     (T.self as! Something.Type).doSomething() 
    } else { 
     // does something else 
    } 
}