Swift统一访问原则

时间:2016-03-02 23:38:35

标签: swift

swift是否支持uniform access principle?据我所知,以下code表明它不是:

@objc protocol CounterDataSource {
    optional func incrementForCount(count: Int) -> Int
    optional var fixedIncrement: Int { get }
}

class Counter {
    var count = 0
    var dataSource: CounterDataSource?
    func increment() {
        if let amount = dataSource?.incrementForCount?(count) {
            count += amount
        } else if let amount = dataSource?.fixedIncrement {
            count += amount
        }
    }
}

incrementForCount是一个函数,必须以不同方式访问(作为"可选"实现的方法),对吗?

1 个答案:

答案 0 :(得分:0)

我认为这个问题误解了关于统一访问原则的文章,我甚至不确定协议如何适合这里的讨论。

文章未必特别清楚,但有两个关键:

  1. 这句话:

      

    无论语言是什么,重要的是程序员不要违反原则。通常,您会看到破坏统一访问的约定。这方面的一个例子可能是数据访问器名为getAge,而计算访问器名为calcAge。在任何一种情况下,我都以同样的方式命名我的访问者。

  2. 此图片:enter image description here

  3. 因此,对于这个例子,我有一些类Person,它有两个我们关心的属性 - age&的出生日期。

    此类有两种可能的实现方式:

    class Person {
        let birthDate: NSDate
    
        var age: Int {
            NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitYear, fromDate: birthDate, toDate: NSDate(), options: nil).year
        }
    
        init(birthDate: NSDate) {
            self.birthDate = birthDate
        }
    }
    

    或者...

    class Person {
        let birthDate: NSDate
        let age: Int
    
        init(birthDate: NSDate, age: Int) {
            self.birthDate = birthDate
            self.age = age
        }
    }
    

    在一个案例中,我们有一个计算年龄,在另一个案例中,我们有一个存储年龄。

    但在这两种情况下,我们都以同样的方式访问它们。

    如果第一种情况下的计算属性被替换为函数,那么违反统一访问原则就会发挥作用:calculateAge() -> Int

    来电者不应关心年龄是根据出生日期计算还是存储财产。 Swift拥有允许开发人员编写代码而不违反统一访问原则的工具。

    此外,我们在开发iOS和iOS时使用的框架OS X应用程序很好地符合统一访问原则。方法&属性访问器永远不会以getcalculate前缀命名。属性可以实现为计算属性(或显然,存储属性)。方法可以进行计算或只返回存储的变量。没有什么能阻止这一切。

    为了完整性,采用上述两个Person实现,违反统一访问原则将如下所示:

    class Person {
        let birthDate: NSDate
    
        var calculateAge: Int {
            NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitYear, fromDate: birthDate, toDate: NSDate(), options: nil).year
        }
    
        init(birthDate: NSDate) {
            self.birthDate = birthDate
        }
    }
    

    或者...

    class Person {
        let birthDate: NSDate
        let getAge: Int
    
        init(birthDate: NSDate, age: Int) {
            self.birthDate = birthDate
            getAge = age
        }
    }