如何从这个Swift类创建一个基础,以便它可以继承?

时间:2016-03-27 00:53:38

标签: ios swift

我有一个名为UserManager的课程。

public class UserManager{
    static let sharedInstance = UserManager()
    let center = NSNotificationCenter.defaultCenter()
    let queue = NSOperationQueue.mainQueue()

    var resources = Dictionary<Int, User>()
    var clients = Dictionary<Int, Set<String>>()

    private init(){

    }

    private func addToClientMap(id: Int, clientName: String){
        if clients[id] == nil {
            clients[id] = Set<String>()
            clients[id]!.insert(clientName)
        }else{
            clients[id]!.insert(clientName)
        }
    }

    func getResource(id: Int, clientName: String) -> User?{
        if let resource = resources[id] {
            addToClientMap(id, clientName: clientName)
            return resource
        }else{
            return nil
        }
    }

    func createResource(data:JSON, clientName: String) -> User? {
        if let id = data["id"].int {
            if let resource = resources[id] { 
                addToClientMap(id, clientName: clientName)
                return resource
            }else{ 
                resources[id] = mapJSONToUser(data) //need to make generic
                addToClientMap(id, clientName: clientName)
                return resources[id]
            }
        }
        return nil
    }

    func releaseResource(id: Int, clientName: String){
        if clients[id] != nil {
            clients[id]!.remove(clientName)
            if clients[id]!.count == 0 { 
                resources.removeValueForKey(id)
                clients.removeValueForKey(id)
            }
        }
    }
}

请注意,我有一个名为User的对象,它在本课程的任何地方都使用过。

我希望有一个名为PostManagerAdminManager的课程,它们使用与上述课程相同的逻辑。

我可以简单地复制并粘贴上面的代码,并使用UserPost 替换对象Admin。但是......显然这是不好的做法。

我该怎么做才能接受任何资源?不只是User

2 个答案:

答案 0 :(得分:1)

这样做最明显的方法是将所有通用功能嵌入到泛型类中,然后继承你的UserManager:

protocol Managable {
    init(json:JSON)
}

public class Manager<T:Manageable> {
    let center = NSNotificationCenter.defaultCenter()
    let queue = NSOperationQueue.mainQueue()

    var resources = Dictionary<Int, T>()
    var clients = Dictionary<Int, Set<String>>()

    private init(){

    }

    private func addToClientMap(id: Int, clientName: String){
        if clients[id] == nil {
            clients[id] = Set<String>()
            clients[id]!.insert(clientName)
        }else{
            clients[id]!.insert(clientName)
        }
    }

    func getResource(id: Int, clientName: String) -> T?{
        if let resource = resources[id] {
            addToClientMap(id, clientName: clientName)
            return resource
        }else{
            return nil
        }
    }

    func createResource(data:JSON, clientName: String) -> T? {
        if let id = data["id"].int {
            if let resource = resources[id] {
                addToClientMap(id, clientName: clientName)
                return resource
            }else{
                resources[id] = T(json:data) //need to make generic
                addToClientMap(id, clientName: clientName)
                return resources[id]
            }
        }
        return nil
    }

    func releaseResource(id: Int, clientName: String){
        if clients[id] != nil {
            clients[id]!.remove(clientName)
            if clients[id]!.count == 0 {
                resources.removeValueForKey(id)
                clients.removeValueForKey(id)
            }
        }
    }
}

class User : Managable {
    required init(json:JSON) {

    }
}

class UserManager : Manager<User> {
    static var instance = UserManager()
}

现在,任何实现Manageable协议的类(即,它具有init(json:JSON)方法都可以具有Manager类变体。请注意,因为泛型类不能具有静态属性,这已被移入子类。

答案 1 :(得分:0)

鉴于继承可以隐藏实现细节,如果不需要引用语义,则使用结构的协议+关联类型(泛型)实现可能更安全,可以说更“Swifty”。

使用关联类型(Swift 2.2)定义您的协议或输入别名(Swift 2.1):

protocol Manager {
    associatedtype MyManagedObject   // use typealias instead for Swift 2.1

    func getResource(id: Int, clientName: String) -> MyManagedObject?
    func createResource(data: JSON, clientName: String) -> MyManagedObject?
    func releaseResource(id: Int, clientName: String)
}

然后您的实施变为:

public struct UserManager: Manager {
    typealias MyManagedObject = User

    func getResource(id: Int, clientName: String) -> User? { ... }
    func createResource(data: JSON, clientName: String) -> User? { ... }
    func releaseResource(id: Int, clientName: String) { ... }
}

您可以轻松地使用相同的协议进一步添加对象,指定“MyManagedObject”应该是什么:

public struct PostManager: Manager {
    typealias MyManagedObject = Post

    func getResource(id: Int, clientName: String) -> Post? { ... }
    func createResource(data: JSON, clientName: String) -> Post? { ... }
    func releaseResource(id: Int, clientName: String) { ... }
}

我建议详细阅读有关协议和泛型的更多信息(网上有很多例子,Apple's documentation is a good place to start)。