1

NSData を引数として取る関数を持つプロトコル拡張 JsonProcess を実装しようとしていますが、このような自己要件を使用してさまざまなプロトコル拡張を作成したいと考えています

extension JSONResource where Self: Login {
    func proccessJSON(data: NSData) -> Self{
        return Login()
    }
}

しかし、コンパイラはエラーを表示します

タイプ 'Login' の戻り式を戻りタイプ 'Self' に変換できません

Login クラスは次のように定義されます

class Login: NSObject {
    var username: String?
    var firstName: String?
}

NSData をシリアル化し、Login クラスのインスタンスを作成して入力し、返そうとした場合、ここで何を返す必要がありますか?

4

2 に答える 2

1

ここでの問題は、Selfよりもタイプ固有である可能性があることですLogin。のサブクラスを作成するとしましょうLogin:

class TopSecretLogin : Login {
    var topSecret : String?
}

のインスタンスでプロトコル拡張を使用するようになると(そもそも が に準拠しているとTopSecretLogin仮定して)、メソッドは を返すと言いますが、これがこの場合です。ただし、 を返そうとしています。したがって、サブクラスを期待するものにスーパークラスを渡すことができないため、コンパイラは満足しません。LoginJSONResourceprocessJSONSelfTopSecretLoginLogin

Login解決策は、サブクラス化するつもりかどうかによって異なります。サブクラス化するつもりがない場合は、単にメソッド シグネチャを a を返すように変更LoginLoginfinal class.

これを意図している場合は、必須の初期化子を に追加して、プロトコル拡張でLoginの任意のインスタンスを構築できるようにする必要があります。Self設定例は次のようになります。

protocol JSONResource {}

class Login : NSObject, JSONResource {

    var username: String?
    var firstName: String?

    required override init() {
        super.init()
    }
}

class TopSecretLogin : Login {

    var topSecret : String?

    required init() {
        super.init()
    }
}

extension JSONResource where Self : Login {
    func processJSON(data: NSData) -> Self {

        // do some processing...

        return Self()
    }
}

let someData = // ...

let l = Login()
l.processJSON(someData) // returns Login

let t = TopSecretLogin()
t.processJSON(someData) // returns TopSecretLogin

processJSONとはいえ、インスタンスメソッドではなく静的メソッドの方が理にかなっているのではないでしょうか? 私には、インスタンスで操作する必要があるようには見えません。指定された のセットから新しいインスタンスを作成するだけですNSData

processJSONまた、プロトコル要件を作成することを検討することもJSONResourceできprocessJSONます。その場合Login、メソッドを実装するために、プロトコル自体ではなく拡張する必要があります。self.init()その後、静的スコープまたはインスタンス スコープで新しいインスタンスを作成できますself.dynamicType.init()

また、初期化子を使用してこれを行うことを検討することもできます。

protocol JSONResource {
    init(jsonData:NSData)
}

class Login : NSObject, JSONResource {

    var username: String?
    var firstName: String?

    required init(jsonData:NSData) {

        // do some processing

        super.init()
    }
}

class TopSecretLogin : Login {

    var topSecret : String?

    required init(jsonData:NSData) {

        // do some processing

        super.init(jsonData:jsonData)
    }
}

let someData = // ...

let l = Login(jsonData: someData) // returns Login

let t = TopSecretLogin(jsonData: someData) // returns TopSecretLogin
于 2016-06-06T13:00:00.323 に答える
1

準拠するオブジェクトSelfがクラスの場合にのみ拡張が適用されると指定したため、次のようにLogin拡張を記述する必要があります。

extension JSONResource where Self: Login {
    func proccessJSON(data: NSData) -> Login {
        return Login()
    }
}
于 2016-06-06T12:30:32.730 に答える