访问控制和代码组织

swift类型的属性,方法初始化方法可以是公开的,甚至是一些内部类型。这些元素被称为代码的接口。

随着代码复杂性的增加,在软件设计方面,控制这些接口成为一个重要的问题。你可能希望给你的代码创建一个担当“助手”的方法或属性,这个“助手”可以追踪到内部状态,但是你又不希望这个“助手”成为你代码的一部分。

swift通过一个叫“访问控制”的重要区域解决这个问题。这个区域可以让你控制代码中可见的接口。访问控制让你,还有库的作者,向用户隐藏代码实现的复杂性。有时隐藏内部状态,好像没有变化一样。你的公共接口应该始终保持这样。防止直接访问类的内部状态,并维持不变是一种基本的软件设计理念,他被称作封装。在本章节你会了解什么是访问控制,如何解决和应用他。

由于缺乏访问控制而引起的问题

想象一下,某个时间,你写了一个银行的库,这个库将帮助你的客户(其他银行)编写他们的银行软件。

在playground中,写一个协议

/// A protocol describing core functionality for an account
protocol Account {
  associatedtype Currency
  var balance: Currency { get }
  func deposit(amount: Currency)
  func withdraw(amount: Currency)
}

这个代码是创建一个Account协议,协议描述任何帐户应该具有存款、取款和检查资金余额的功能。

现在添加一个符合标准的类型,代码如下:

typealias Dollars = Double
/// A U.S. Dollar based "basic" account.
class BasicAccount: Account {
  var balance: Dollars = 0.0
  func dposit(amount: Dollars) {
    balance += amount
  }
  func withdraw(amount: Dollars) {
      if amount <= balance {
        balance -= amount
       } else {
        balance = 0 
        }
      } 
    }

BasicAccount遵循协议Account,通过对balance进行相加,相减,实现了deposit(amount:) 和withdraw(amount:) 方法,Dollars类型,是double的别名。

虽然这个代码很简单,但是你还是会发现一个问题,balance这个属性在Account协议中是只读的,换句话说它只定义了get。然鹅,BasicAccount要求balance是可变的,当资金增加或减少的时候,去更新balance。

啥也不能阻挡别的代码直接修改balance的值。

// 创建一个新的账号 account
let account = BasicAccount()
// 增加或减少资金
account.deposit(amount: 10.00)
account.withdraw(amount: 5.00)
// ... 或者做一些自己想做的事情!
account.balance = 1000000.00

即使你很谨慎的设计Account协议,只让他减少或增加资金,但是BasicAccount的实现却可以直接修改balance的值,任何代码都可以。

幸运的是你可以使用访问控制,限制代码对其他类型、文件甚至软件模块可见的范围。

你可能感兴趣的:(访问控制和代码组织)