Swift에서 일반 프로토콜을 만드는 방법은 무엇입니까?
제네릭 입력을 받아 제네릭 값을 반환하는 메서드로 프로토콜을 만들고 싶습니다.
이것은 지금까지 시도한 것이지만 구문 오류가 발생합니다.
선언되지 않은 식별자 T 사용.
내가 도대체 뭘 잘못하고있는 겁니까?
protocol ApiMapperProtocol {
func MapFromSource(T) -> U
}
class UserMapper: NSObject, ApiMapperProtocol {
func MapFromSource(data: NSDictionary) -> UserModel {
var user = UserModel() as UserModel
var accountsData:NSArray = data["Accounts"] as NSArray
return user
}
}
프로토콜에 대해서는 약간 다릅니다. Apple 문서 에서 "Associated Types" 를 보십시오 .
이것이 귀하의 예에서 사용하는 방법입니다.
protocol ApiMapperProtocol {
associatedtype T
associatedtype U
func MapFromSource(_:T) -> U
}
class UserMapper: NSObject, ApiMapperProtocol {
typealias T = NSDictionary
typealias U = UserModel
func MapFromSource(_ data:NSDictionary) -> UserModel {
var user = UserModel()
var accountsData:NSArray = data["Accounts"] as NSArray
// For Swift 1.2, you need this line instead
// var accountsData:NSArray = data["Accounts"] as! NSArray
return user
}
}
Lou Franco의 대답에 대해 조금 설명하려면 특정을 사용하는 메서드를 만들려면 ApiMapperProtocol
다음과 같이하십시오.
protocol ApiMapperProtocol {
associatedtype T
associatedtype U
func mapFromSource(T) -> U
}
class UserMapper: NSObject, ApiMapperProtocol {
// these typealiases aren't required, but I'm including them for clarity
// Normally, you just allow swift to infer them
typealias T = NSDictionary
typealias U = UserModel
func mapFromSource(data: NSDictionary) -> UserModel {
var user = UserModel()
var accountsData: NSArray = data["Accounts"] as NSArray
// For Swift 1.2, you need this line instead
// var accountsData: NSArray = data["Accounts"] as! NSArray
return user
}
}
class UsesApiMapperProtocol {
func usesApiMapperProtocol<
SourceType,
MappedType,
ApiMapperProtocolType: ApiMapperProtocol where
ApiMapperProtocolType.T == SourceType,
ApiMapperProtocolType.U == MappedType>(
apiMapperProtocol: ApiMapperProtocolType,
source: SourceType) -> MappedType {
return apiMapperProtocol.mapFromSource(source)
}
}
UsesApiMapperProtocol
이제 주어진와 SourceType
호환되는 s 만 허용하도록 보장됩니다 ApiMapperProtocol
.
let dictionary: NSDictionary = ...
let uses = UsesApiMapperProtocol()
let userModel: UserModel = uses.usesApiMapperProtocol(UserMapper()
source: dictionary)
In order to achieve having generics and as well having it declare like this let userMapper: ApiMapperProtocol = UserMapper()
you have to have a Generic Class conforming to the protocol which returns a generic element.
protocol ApiMapperProtocol {
associatedtype I
associatedType O
func MapFromSource(data: I) -> O
}
class ApiMapper<I, O>: ApiMapperProtocol {
func MapFromSource(data: I) -> O {
fatalError() // Should be always overridden by the class
}
}
class UserMapper: NSObject, ApiMapper<NSDictionary, UserModel> {
override func MapFromSource(data: NSDictionary) -> UserModel {
var user = UserModel() as UserModel
var accountsData:NSArray = data["Accounts"] as NSArray
return user
}
}
Now you can also refer to userMapper
as an ApiMapper
which have a specific implementation towards UserMapper
:
let userMapper: ApiMapper = UserMapper()
let userModel: UserModel = userMapper.MapFromSource(data: ...)
You can use templates methods with type-erasure...
protocol HeavyDelegate : class {
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R
}
class Heavy<P, R> {
typealias Param = P
typealias Return = R
weak var delegate : HeavyDelegate?
func inject(p : P) -> R? {
if delegate != nil {
return delegate?.heavy(self, shouldReturn: p)
}
return nil
}
func callMe(r : Return) {
}
}
class Delegate : HeavyDelegate {
typealias H = Heavy<(Int, String), String>
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R {
let h = heavy as! H
h.callMe("Hello")
print("Invoked")
return "Hello" as! R
}
}
let heavy = Heavy<(Int, String), String>()
let delegate = Delegate()
heavy.delegate = delegate
heavy.inject((5, "alive"))
참고URL : https://stackoverflow.com/questions/24469913/how-to-create-generic-protocols-in-swift
'program story' 카테고리의 다른 글
Xcode 5 및 iOS 7 : 아키텍처 및 유효한 아키텍처 (0) | 2020.10.05 |
---|---|
Maven 2로 실행 가능한 jar 빌드 (0) | 2020.10.05 |
jQuery를 사용하여 너비를 백분율로 설정 (0) | 2020.10.05 |
GNU의 재귀 와일드 카드는? (0) | 2020.10.05 |
intellij 아이디어 실행 구성 백업 (0) | 2020.10.05 |