ここでの問題は、Self
よりもタイプ固有である可能性があることですLogin
。のサブクラスを作成するとしましょうLogin
:
class TopSecretLogin : Login {
var topSecret : String?
}
のインスタンスでプロトコル拡張を使用するようになると(そもそも が に準拠しているとTopSecretLogin
仮定して)、メソッドは を返すと言いますが、これがこの場合です。ただし、 を返そうとしています。したがって、サブクラスを期待するものにスーパークラスを渡すことができないため、コンパイラは満足しません。Login
JSONResource
processJSON
Self
TopSecretLogin
Login
Login
解決策は、サブクラス化するつもりかどうかによって異なります。サブクラス化するつもりがない場合は、単にメソッド シグネチャを a を返すように変更Login
しLogin
、final 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