Swift中的协议继承+委托

Ixx*_*Ixx 12 ios swift

我有一个有代表的班级.我创建了一个子类,它也有一个委托.我想让第二个委托使用的协议扩展用于第一个委托的协议:

protocol MySuperClassProtocol {
    func foo()
}

class MySuperClass {
    var delegate:MySuperClassProtocol?
}

protocol MySubClassProtocol:MySuperClassProtocol {
    func bar()
}

class MySubClass: MySuperClass {
    override var delegate:MySubClassProtocol? // compiler error - "cannot override..."

    func test() {
        delegate?.foo()
        delegate?.bar()
    }
}

class UserClass:MySubClassProtocol {
    func foo() {
        println("foo!")
    }
    func bar() {
        println("bar")
    }
} 
Run Code Online (Sandbox Code Playgroud)

有办法解决这个问题吗?我看到的唯一可能的解决方案是使2个协议彼此独立,并使用不同的名称.像这样:

protocol MySuperClassProtocol {
    func foo()
}

class MySuperClass {
    var mySuperClassDelegate:MySuperClassProtocol?
}

protocol MySubClassProtocol {
    func bar()
}

class MySubClass: MySuperClass {
    var mySubClassDelegate:MySubClassProtocol?

    func test() {
        mySuperClassDelegate?.foo()
        mySubClassDelegate?.bar()
    }
}

class UserClass:MySuperClassProtocol, MySubClassProtocol {
    func foo() {
        println("foo!")
    }
    func bar() {
        println("bar")
    }
}
Run Code Online (Sandbox Code Playgroud)

但这看起来有点奇怪+不会让我使用委托 - "委托"的命名约定.

cou*_*elk 5

我试图在一段时间内找到一个理想的解决方案,但是无法提出更好的解决方案:

protocol BaseDelegateProtocol: class { }

class BaseDelegate: BaseDelegateProtocol { }

class BaseActor {
    weak var delegate: BaseDelegate? = nil
}

// MARK: -

protocol ConcreteDelegateProtocol: class {
    func doSomething()
}

class ConcreteDelegate: BaseDelegate, ConcreteDelegateProtocol {
    func doSomething() {
        // Do something
    }
}

class ConcreteActor: BaseActor {
    private weak var concreteDelegate: ConcreteDelegateProtocol? = nil

    override var delegate: BaseDelegate? {
        didSet {
            concreteDelegate = delegate as? ConcreteDelegateProtocol
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以上工作在XCode 7/Swift 2中.

  • 这种模式允许在继承的过程中采用越来越多的协议BaseDelegate.
  • 不需要从另一个继承协议,这有助于保持隔离.
  • didSetdelegate属性上的observer 会自动调用超类,因此不需要super.<blah>显式调用,也没有"忘记"这样做的风险
  • 具体的委托属性可以在每个继承级别保持私有,从而减少混乱.


Ром*_*ров 5

对不起,我发现的唯一一个解决方案是:

protocol SuperClassDelegate {
    func first_method()
}

class SuperClass {
    var delegate: SuperClassDelegate?

    func do_something() {
        delegate?.first_method()
    }
}

protocol SubClassDelegate: SuperClassDelegate {
    func second_method()
}

class SubClass: SuperClass {
    private var subDelegate: SubClassDelegate?
    override var delegate: SuperClassDelegate? {
        get { return self.subDelegate }
        set { self.subDelegate = newValue as! SubClassDelegate? }
    }

    //override func do_something() {
    //  super.do_something()
    //  subDelegate?.second_method()
    //}

    func do_something_other() {
        //subDelegate?.first_method()
        self.do_something()
        subDelegate?.second_method()
    }
}

class InheritanceAndDelegation: SubClassDelegate {
    let obj = SubClass()

    init() {
        obj.delegate = self
    }

    internal func first_method() {
        print("Hello from SuperClass")
    }

    internal func second_method() {
        print("Hello from SubClass")
    }

    func check() {
        obj.do_something_other()
    }
}

let inheritanceAndDelegation = InheritanceAndDelegation()
inheritanceAndDelegation.check()
//prints:
//Hello from SuperClass
//Hello from SubClass
Run Code Online (Sandbox Code Playgroud)

注释代码也有效。希望它对某人有用。


Mid*_* MP 1

您可以用另一种方式做到这一点,您可以delegate在子类中添加变量并使用它来访问SuperClassProtocol也使用delegate?.foo().

protocol MySuperClassProtocol {
    func foo()
}

class MySuperClass {
    //var delegate:MySuperClassProtocol?
}

protocol MySubClassProtocol:MySuperClassProtocol {
    func bar()
}

class MySubClass: MySuperClass {
    var delegate:MySubClassProtocol?

    func test() {
        delegate?.foo()
        delegate?.bar()
    }
}

class UserClass:MySubClassProtocol {
    func foo() {
        println("foo!")
    }
    func bar() {
        println("bar")
    }
}
Run Code Online (Sandbox Code Playgroud)

但这种方法的问题是你永远不能MySuperClassProtocol独立使用,除非你创建一个MySuperClass仅用于声明delegate变量的新子类。