2

我有一个以这种格式构建的相当大的项目:

class One : FirstThree {

    fileprivate var integers: [Int] {
        return [1, 2, 3, 101, 102]
    }

    override func allIntegers() -> [Int] {
        return integers
    }

    func doStuffForOne() {
        //does stuff unrelated to the other classes
    }
}

class Two : FirstThree {

    fileprivate var integers: [Int] {
        return [1, 2, 3, 201]
    }

    override func allIntegers() -> [Int] {
        return integers
    }

    func doStuffForTwo() {
        //does stuff unrelated to the other classes
    }
}

class Three : Numbers {

    fileprivate var integers: [Int] {
        return [301, 302, 303]
    }

    override func allIntegers() -> [Int] {
        return integers
    }

    func doStuffForThree() {
        //does stuff unrelated to the other classes
    }
}

class FirstThree : Numbers {

    fileprivate var integers: [Int] {
        return [1, 2, 3]
    }

    override func allIntegers() -> [Int] {
        return integers
    }

    func doStuffForFirstThree() {
        //does stuff unrelated to the other classes
    }
}

class Numbers {

    func allIntegers() -> [Int] {
        fatalError("subclass this")
    }

    func printMe() {
        allIntegers().forEach({ print($0) })
    }
}

Numbers有很多方法printMe(),我希望我的所有子类的任何实例都能够调用。

Numbers还有一个allIntegers()函数,我希望这些子类的任何实例都能够调用。作为变量,哪个可能更好?但是我不能覆盖子类中的变量。因此,我在每个子类中使用相同的私有变量integers,由allIntegers().

还要注意它自己的实例Numbers永远不应该调用allIntegers(),它应该只在子类上调用。

最后,请注意一些子类包含相同的对象1, 2, 3,然后每个子类都有一些自定义整数。但不是所有的子类。如果我后来决定所有这些子类都需要一个4整数,我必须手动遍历每个类并将 a4打入数组,这显然容易出错。

我已经阅读了面向协议的编程,并且觉得可能有一个解决方案,或者我会很感激任何其他建议和创造性的方法来构建一个更好的项目。

谢谢!

编辑

所有子类都是不同的,因为它们也有自己的功能要执行。我已经更新了代码以反映这一点。

想象一下,一个给定的类 likeOne在整个代码库中被初始化了很多次,并且总是用完全相同的integers. 放:

let one = One(integers: [1, 2, 3, 101, 102])

整个代码库都容易出错。

希望这可以解决我提出的人为示例的一些问题。

解决方案

感谢大家的帮助。这是我想出的解决方案(请假设所有类都有自己独特的方法)。

class One : FirstThree {

    override init() {
        super.init()
        self.integers = super.integers + [101, 102]
    }
}

class Two : FirstThree {

    override init() {
        super.init()
        self.integers = super.integers + [201]
    }
}

class Three : Numbers {
    var integers  = [301, 302, 303]
}

class FirstThree : Numbers {
    let integers = [1, 2, 3]
}

protocol Numbers {
    var integers: [Int] { get }
    func printMe()
}

extension Numbers {
    func printMe() {
        integers.forEach({ print($0) })
    }
}
4

3 回答 3

4

更新

鉴于您添加到问题中的新信息,这是一种可能的方法

我真的无法抗拒,所以我稍微重构了命名:D

现在你有一个协议

protocol HasIntegers {
    var integers: [Int] { get }
    func printMe()
}

以及添加 printMe 功能的协议扩展。

extension HasIntegers {
    func printMe() {
        integers.forEach { print($0) }
    }
}

最后,您有 2 个类(代码中有 4 个类,但想法没有改变)。

A 类始终包含[1, 2, 3, 101, 102]并拥有自己的一组方法 ( doSomething())

class A: HasIntegers {
    fileprivate (set) var integers: [Int] = [1, 2, 3, 101, 102]
    func doSomething() { }
}

该类B始终包含 [1, 2, 3, 201] 并具有一组不同的方法 ( doSomethingElse())

class B: HasIntegers {
    fileprivate (set) var integers: [Int] = [1, 2, 3, 201]
    func doSomethingElse() { }
}

A 和 B 都符合 HasInteger,然后自动接收printMe()方法。


旧答案

你不需要那个

我在您的代码中看到了很多东西:

  • 遗产
  • 协议(确实没有协议:D)
  • 计算属性
  • 功能
  • 课程(很多!)

但是没有明显的理由使用所有这些东西:)

你可以简单地写

class Box {
    fileprivate (set) var integers: [Int]

    init(integers:[Int]) {
        self.integers = integers
    }

    func printMe() {
        integers.forEach { print($0) }
    }
}

let one = Box(integers: [1, 2, 3, 101, 102])
let two = Box(integers: [1, 2, 3, 201])
let three = Box(integers: [1, 2, 3, 301, 302, 303])
let four = Box(integers: [401, 402])
于 2017-01-20T20:08:11.610 回答
2

使用您的常用操作定义协议,包括objects访问器:

protocol Numbers {

    /// My objects. By default, `Numbers.commonObjects`. Subclasses can override to include more objects.
    var objects: [Int] { get }

    func printMeThatConformersCanOverride()

}

在扩展中提供默认实现:

extension Numbers {

    /// The default implementation of `objects`, which just returns `Numbers_defaultObjects`.
    var objects: [Int] { return Numbers_defaultObjects }

    /// Since this is declared in the protocol, conformers can override it.
    func printMeThatConformersCanOverride() {
        Swift.print("Numbers " + objects.map({ "\($0)" }).joined(separator: " "))
    }

}

/// It would be nice to make this a member of `Numbers`, but Swift won't let us.
private let Numbers_defaultObjects = [1, 2, 3]

因为这些定义实现了协议中声明的东西,所以符合的类型可以覆盖它们。您还可以在扩展中定义符合类型无法覆盖的内容:

extension Numbers {

    /// Since this is not declared in the protocol, conformers cannot override it. If you have a value of type `Numbers` and you call this method on it, you get this version.
    func printMeThatConformersCannotOverride() {
        Swift.print("Numbers " + objects.map({ "\($0)" }).joined(separator: " "))
    }

}

然后我们可以实现一个符合协议的类。我们可以使用 alet来覆盖objects

class One: Numbers {

    /// You can use a `let` to override `objects`.
    let objects: [Int] = Numbers_defaultObjects + [101, 102]

    func doStuffForOne() {
        Swift.print("I'm doing One-specific stuff with \(objects)")
    }

    func printMeThatConformersCanOverride() {
        Swift.print("One wins! You don't care what type I am.")
    }

    func printMeThatConformersCannotOverride() {
        Swift.print("One wins! You think I'm type One, not type Numbers.")
    }

}

我们可以使用存储的属性来覆盖objects

class Two: Numbers {

    /// You can use a stored property to override `objects`.
    var objects: [Int] = Numbers_defaultObjects + [201]

    func doStuffForTwo() {
        Swift.print("I'm doing Two-specific stuff with \(objects)")
    }

}

我们可以使用计算属性来覆盖objects

class Three: Numbers {

    /// You can use a computed property to override `objects`.
    var objects: [Int] { return [301, 302, Int(arc4random())] }

    func doStuffForThree() {
        Swift.print("I'm doing Three-specific stuff with \(objects)")
    }

}

我们甚至不必使用类类型。我们可以使用结构类型来代替:

struct Four: Numbers {
    func doStuffForFour() {
        Swift.print("I'm doing Four-specific stuff with \(objects)")
    }
}

我在上面说过,你可以在扩展中定义东西,如果它们没有在协议中声明,那么符合类型就不能覆盖它们。这在实践中可能有点令人困惑。如果你尝试One重写一个在扩展中定义但不是协议一部分的方法,会发生什么?

let one = One()

one.printMeThatConformersCanOverride()
// output: One wins! You don't care what type I am.

(one as Numbers).printMeThatConformersCanOverride()
// output: One wins! You don't care what type I am.

one.printMeThatConformersCannotOverride()
// output: One wins! You think I'm type One, not type Numbers.

(one as Numbers).printMeThatConformersCannotOverride()
// output: Numbers 1 2 3 101 102

对于协议中声明的方法,您运行属于该值的运行时类型的版本。对于未在协议中声明的方法,您运行属于该值的编译时类型的版本。

于 2017-01-20T21:07:01.483 回答
1

我假设你有一个非常复杂的应用程序,这些带有一些虚拟函数的简单类只是一个简单的例子。所以这是一种使用协议重构它的方式:

第一步可以是将Numbers基类更改为具有默认实现的协议,例如:

class One : Numbers {

    fileprivate var _objects: [Int] {
        return [1, 2, 3, 101, 102]
    }

    func objects() -> [Int] {
        return _objects
    }
}

class Two : Numbers {

    fileprivate var _objects: [Int] {
        return [1, 2, 3, 201]
    }

    func objects() -> [Int] {
        return _objects
    }
}

class Three : Numbers {

    fileprivate var _objects: [Int] {
        return [1, 2, 3, 301, 302, 303]
    }

    func objects() -> [Int] {
        return _objects
    }
}

class Four : Numbers {

    fileprivate var _objects: [Int] {
        return [401, 402]
    }

    func objects() -> [Int] {
        return _objects
    }
}

protocol Numbers {
    func objects() -> [Int];
    func printMe() ;
}

//Default implementation of the services of Numbers.
extension Numbers {
    func objects() -> [Int] {
        fatalError("subclass this")
    }

    func printMe() {
        objects().forEach({ print($0) })
    }
}

然后让我们从 中创建一个变量objects(),正如您在问题中所说的(在这种情况下objects是只读的,您不能在实例中更新它):

class One : Numbers {

    //Protocol specifying only the getter, so it can be both `let` and `var` depending on whether you want to mutate it later or not :
    let objects = [1, 2, 3, 101, 102]

}

class Two : Numbers {

    var objects =  [1, 2, 3, 201]

}

class Three : Numbers {

    var objects  = [1, 2, 3, 301, 302, 303]

}

class Four : Numbers {

    let objects = [401, 402]

}

protocol Numbers {

    var objects:[Int] { get }
    func printMe() ;
}

//Default implementation of the services of Numbers.
extension Numbers {

    func printMe() {
        objects.forEach({ print($0) })
    }
}

如果objects可以是只读的,您仍然可以为objectsgetter 添加默认实现,例如:

class Four : Numbers {

}

protocol Numbers {

    var objects:[Int] { get }
    func printMe() ;
}

//Default implementation of the services of Numbers.
extension Numbers {

    var objects: [Int] {
        return [401, 402]
    }

    func printMe() {
        objects.forEach({ print($0) })
    }
}
于 2017-01-20T19:53:29.843 回答