共享变量的组合而不是继承

时间:2017-05-06 07:02:48

标签: ios swift inheritance composition

我以前使用的课程可以简化为:

class Whatever {

  var someArray = [Int]()

  func unchangingFunction {
    print("test")
  }

  func functionForOverride() {}

}

我在想办法改善这一点,并且我被告知赞成合成而不是继承,使用如下内容:

protocol Implementation {
  func functionForOverride()
}

final class Whatever {

  var someArray = [Int]() // How can I access this?

  let implementation: Implementation

  init(implementation: Implementation) {
    self.implementation = implementation
  }

  func unchangingFunction() {
    print("test")
  }

  func functionForOverride() {
    implementation.functionForOverride()
  }

}

但是,有了这个,我找不到使用someArray数组做任何事情的方法:

struct Something: Implementation {

  func functionForOverride() {
    print(someArray) // This cannot work
  }

}

使用原始代码,我可以访问和更改someArray但是我想要,但是用这种新方法,我想不出一个简单的解决方案。

2 个答案:

答案 0 :(得分:2)

我认为我们应该使用"真实"例子,以使事情更清楚。

继承(及其错误的原因)

我们有以下课程

class Robot {
    var battery = 0

    func charge() {
        print("⚡️")
        battery += 1
    }
}

class Human {
    func eat() {
        print("")
    }
}

class RobotCleaner: Robot {
    func clean() {
        print("")
    }
}

class HumanCleaner: Human {
    func clean() {
        print("")
    }
}

代码重复!!!

正如您所见,clean()RobotCleaner中的HumanCleaner方法重复。你能找到一种方法(使用继承)来删除代码重复吗?

好的想一想,我等下一段...:)

...

哦,你来了!没有办法通过继承来解决这个问题吗?好吧,让我们看看我们可以用组合做些什么。

作文(经典方式)

让我们定义以下3个协议和相关组件

protocol Robot {
    mutating func charge()
}
struct RobotComponent: Robot {
    var battery = 0
    mutating func charge() {
        print("⚡️")
        battery += 1
    }
}

protocol Human {
    func eat()
}
struct HumanComponent: Human {
    func eat() {
        print("")
    }
}

protocol Cleaner {
    func clean()
}
struct CleanerComponent: Cleaner {
    func clean() {
        print("")
    }
}

现在我们可以构建前3个元素的任意组合

struct RobotCleaner: Robot, Cleaner {
    var robotComponent = RobotComponent()
    let cleanerComponent = CleanerComponent()

    mutating func charge() {
        robotComponent.charge()
    }

    func clean() {
        cleanerComponent.clean()
    }

}

struct HumanCleaner: Human, Cleaner {
    let humanComponent = HumanComponent()
    let cleanerComponent = CleanerComponent()

    func eat() {
        humanComponent.eat()
    }

    func clean() {
        cleanerComponent.clean()
    }   
}

面向协议的编程:以Swifty方式构成

斯威夫特提供了一种非常巧妙的构图方式。

首先,让我们定义以下3个协议(及相关扩展)。

protocol Robot {
    var battery: Int { get set }
}
extension Robot {
    mutating func charge() {
        print("⚡️")
        battery += 1
    }
}

protocol Human { }
extension Human {
    func eat() {
        print("")
    }
}

protocol Cleaner { }
extension Cleaner {
    func clean() {
        print("")
    }
}

现在我们可以创建一个包含前3个实体的任意组合的Type。让我们看看如何。

struct HumanCleaner: Human, Cleaner { }
struct RobotCleaner: Robot, Cleaner {
    var battery: Int = 0
}

答案 1 :(得分:1)

如果'Implementation'需要'someArray'来做它想要做的事情,那么你应该让'Implementation'要求任何符合它的对象也声明'someArray'

像这样:

protocol Implementation {
    var someArray: [Int]
}

如果你知道你想用'someFunction'做什么,那么你可以用这样的协议扩展来给它一个默认的实现:

extension Implementation {
    func someFunction() {
        //you can do some stuff with someArray here
    }
}

然后,当你遵守'Implementation'时,你需要声明'someArray'而不是'someFunction',除非你想要覆盖默认函数。

E.g。

class MyClass: Implementation {
     var someArray: [Int]!

     init() {}
}

请注意,MyClass现在可以访问'someFunction',它可以在您的类中自由覆盖,并且您可以添加任意数量的函数来实现'实现的扩展。