首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展协议以实现不同的行为

扩展协议以实现不同的行为
EN

Stack Overflow用户
提问于 2016-12-15 17:46:44
回答 5查看 1.8K关注 0票数 4

快速问题,比如说你有一个协议叫:

代码语言:javascript
复制
protocol MakeSound {
   func bark()
}

一个超类Dog,它实现了叫和游泳:

代码语言:javascript
复制
class Dog: MakeSound {
}

然后是不同类型的狗,它们扩展了这一点:

代码语言:javascript
复制
class Poodle: Dog {
}

class GermanShephard: Dog {
}

class SheepDog: Dog {
}

但是狮子狗叫,他们不叫…所有的狗都会叫,它们只是用不同的方式…我如何给他们特定的树皮行为?

扩展协议?...

代码语言:javascript
复制
extension MakeSound {
    func bark()
    func yapper()
}

但是贵宾犬和德国牧羊犬都有这两种行为(狂叫的德国牧羊犬?!)

如果我做了2个扩展并使用where Self =?

代码语言:javascript
复制
extension MakeSound where Self: GermanShephard {
    func bark() {
        print("Bark")
    }
}

extension MakeSound where Self: Poodle{
    func yapper() {
        print("yap yap")
    }
}

但我只能检查一种类类型,或狗类型。SheepDogs也会叫,但我不能在这里检查...

我知道在Java中你可以用几种不同的实现来扩展一个接口。如何使用Swift中的协议来解决此问题?

EN

回答 5

Stack Overflow用户

发布于 2016-12-15 18:19:12

如果我没理解错你的问题,也许这会有所帮助。

您可以通过扩展协议来为bark()提供一个默认实现。然后,在符合该协议的其他类上,您可以更改bark函数的实现:

代码语言:javascript
复制
protocol Bark {
   func bark()
}

//default implementation
extension Bark {
      func bark() { print("Bark") }
}

class Dog: Bark {}

//By calling bark func in Poodle, you change the default implementation.
class Poodle: Dog {
   func bark() { print("Yap") }
}

class GermanShephard: Dog {
     func bark() { print("Woof") }
}

let dog = Dog()
let poodle = Poodle()
let germanShephard = GermanShephard()

dog.bark()
//Bark
poodle.bark()
//Yap
germanShephard.bark()
//Woof

您也可以不执行任何默认实现,只需为每种情况添加您自己的实现

注释后编辑:

这是协议有用的主要原因之一。它们消除了与子类化相关的紧密耦合。这是一个基本的例子,因为整个主题包含了很多信息,但是您可以创建一个协议DogRepresentable并分配所有狗实现的所有默认属性和功能,而不是将Dog子类化。然后,您可以扩展DogRepresentable where self: UIViewController并实现默认功能:

代码语言:javascript
复制
protocol Barkable {
    func bark()
}

protocol DogRepresentable: Barkable {
//properties and functions all dogs will have with same implementation
}

extension DogRepresentable where Self: UIViewController {
//default implementation for functions all dogs will use
}

通过将Barkable赋值给DogRepresentable,您知道任何符合DogRepresentable的类也必须符合Barkable。

现在,当您将DogRepresentable分配给一个类时,它将获得基类将获得的所有默认实现,并且您将被迫调用bark()函数以正确遵守协议:

代码语言:javascript
复制
class Dog: DogRepresentable {
   func bark() { print("Bark") }
} 

class Poodle: DogRepresentable {
   func bark() { print("Yap") }
}

 class GermanShephard: DogRepresentable {
    //Won't conform because it doesn't have bark()
}

这样,您可以获得所有的默认实现,例如基类,但不会出现忘记覆盖超类函数的问题。

根据第二条评论编辑2:

在这种情况下,你最好的选择是离开DogRepresentable而不遵循可叫,然后为不同的类型创建协议:所以如果你有狗叫,你可以做一个协议Yappable,它有一个叫功能和默认实现。然后,您可以使用另一个协议Barkable,该协议具有自己的bark功能和自己的默认实现。然后让类符合它们应该遵循的任何协议。贵宾犬符合Yappable,狗符合Barkable。

通过创建这些独立的协议,您可以将每种情况的功能保留在一个位置,并且只使用您需要的任何一个,从而保持您的代码更干净、更具可读性和干净性。

票数 3
EN

Stack Overflow用户

发布于 2016-12-16 05:24:19

这是一个完美的协议继承用例。

代码语言:javascript
复制
protocol DogSoundMaker {
    func makeSound()
}

protocol Barker: DogSoundMaker {}
protocol Yapper: DogSoundMaker {}
protocol Woofer: DogSoundMaker {}

extension Barker {
    func makeSound() { print("Bark") }
}

extension Yapper {
    func makeSound() { print("Yap yap, I am a glorified rodent") }
}

extension Woofer {
    func makeSound() { print("Woof") }
}

struct Poodle: Yapper {}
struct GermanShephard: Barker {}
struct SheepDog: Woofer {}

Poodle().makeSound()
GermanShephard().makeSound()
SheepDog().makeSound()
票数 2
EN

Stack Overflow用户

发布于 2016-12-15 23:26:27

这就是答案,makeSound协议是由两个不同的叫声协议dogYap和dogBark实现的。这反过来扩展并实现了用于叫声和叫声的不同声音。然后,各种狗类型(扩展狗)的类可以实现dogYap或dogBark,这取决于狗发出的声音类型。

代码语言:javascript
复制
protocol MakeSound {
    func makeSound()
    var canBark: Bool { get }
    var canYap: Bool { get }
}

protocol dogBark: MakeSound {
    func makeSound()
}

protocol dogYap: MakeSound {
    func makeSound()
}

extension dogYap {
    func makeSound() {
        print("Yap")
    }
}

extension dogBark {
    func makeSound() {
        print("bark")
    }
}

extension MakeSound {
    func makeSound() {}
    var canBark: Bool { return self is dogBark }
    var canYap: Bool { return self is dogYap }

}

class Dog {
    var age: Int?
    var colour: UIColor?

}

class Poodle: Dog, dogYap {
}

class GermanShephard: Dog, dogBark  {
}

class SheepDog: Dog, dogBark {
}

//German shephard and Belgian bark in the same way
let germanShep = GermanShephard()
germanShep.makeSound()
germanShep.canBark
germanShep.canYap


let sheepDog = SheepDog()
sheepDog.makeSound()
sheepDog.canBark
sheepDog.canYap

let poodle = Poodle()
poodle.makeSound()
poodle.canBark
poodle.canYap
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41161013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档