【问题标题】:Computed or Stored Property?计算属性还是存储属性?
【发布时间】:2017-06-11 10:00:30
【问题描述】:

所以,我正在将我的 Android 应用程序移植到 iOS 并且我正在使用 Swift (3)。

我了解 Computed 属性的概念,并尝试尽可能多地使用它们,但这让我想到,也许我做得过火了,这将对我的应用程序产生性能影响。

所以我的场景: 我有一个有两个字符串的类,其中一个是我的用户名,它是全球认为我的应用程序,另一个是对手的用户名。所以我的代码是这样的:

class Game {
    let player: String
    let opponent: String
    var iAmPlayer: Bool {
        return player.caseInsensitiveCompare(GlobalUsername) == .orderedSame
    }

    init(player: String, opponent: String) {
        self.player = player
        self.opponent = opponent
    }
}

我经常检查 iAmPlayer 布尔值,以查看用户是否启动了游戏,尤其是在订购游戏对象时。在 java 中,我只有一个在初始化对象时设置的布尔变量。我想知道,如果我在这里只使用存储属性而不是我正在做的事情会更好吗?计算属性是否已优化,或者每次我尝试访问 iAmPlayer var 时都会进行计算?

P.S.:一旦创建了 Game 对象,玩家和对手就不会改变。 (因此让)

【问题讨论】:

  • 是的,每次参考iAmPlayer 时都会进行计算。因此,存储的属性会更有效率。 (我假设不仅playeropponent 都不能改变,而且GlobalUsername 也不能改变?)
  • 这只能在playerGlobalUsername 没有改变的情况下被优化掉,并且只有当编译器可以推断出caseInsensitiveCompare 是引用透明的。这当然是可能的,但您必须亲自查看生成的代码。
  • @Rob 是的,没有一个值可以改变。如果有任何变化,将创建一个新的 Game 对象,因为它们是从我的服务器获取的。我还有一些其他的类,我对 var 做同样的事情,可以改变。计算属性是否更适合那里?
  • @Alexander 所以你的建议是我应该为我的布尔值使用存储属性,因为它无法优化,或者你真的想查看生成的代码? (如果是,怎么做?)
  • @LucasP。在您分析您的应用程序并将其确定为性能问题之前,我会坚持使用您认为最干净和最简单的任何技术。我个人更喜欢存储的财产,但这只是我

标签: ios swift properties


【解决方案1】:

感谢问题下方的其他 cmets 我使用Usermanager.instance.username 而不是GlobalUsername

1.解决方案:将计算移至Init

  • 专业版:未更改任何其他代码
  • con:仍然有对 UserManager 的引用

代码:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = playerName.caseInsensitiveCompare(UserManager.instance.currentUserName) == .orderedSame
    }
}

// Create Game object

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName)

2。解决方法:将当前用户名赋予init

  • pro:没有隐式输出连接 - 对象解耦
  • pro:无需设置用户管理器即可测试
  • 缺点:你必须更改游戏初始化的创建

代码:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String, currentUserName: String) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = playerName.caseInsensitiveCompare(currentUserName) == .orderedSame
    }
}

// Create Game object

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    currentUserName: UserManager.instance.currentUserName)

3。解决方案:将 bool 的计算移到创建之外

  • pro:没有隐式输出连接 - 对象解耦
  • pro:无需设置用户管理器即可测试
  • 专业版:在不更改游戏对象的情况下更改“isCurrentUser”的计算逻辑
  • 缺点:你必须更改游戏初始化的创建

代码:

class Game {
    let playerName: String
    let opponentName: String
    var isCurrentUser: Bool

    init(playerName: String, opponentName: String, isCurrentUser: Bool) {
        self.playerName = playerName
        self.opponentName = opponentName
        self.isCurrentUser = isCurrentUser
    }
}

// Create Game object

var currentUserName = UserManager.instance.currentUserName
var isCurrentUser = dameData.playerName.caseInsensitiveCompare(currentUserName) == .orderedSame

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    isCurrentUser: isCurrentUser)


// Create Game object

var isCurrentUser = UserManager.instance.isCurrentUser(gameData.playerName)

Game(playerName: gameData.playerName, 
    opponentName: gameData.opponentName, 
    isCurrentUser: isCurrentUser)

【讨论】:

    猜你喜欢
    • 2022-08-16
    • 2023-03-19
    • 2014-08-02
    • 1970-01-01
    • 2018-11-29
    • 2018-05-24
    • 2015-04-18
    • 2017-11-04
    • 2021-12-16
    相关资源
    最近更新 更多