【问题标题】:Object oriented style - where to define properties? VBA面向对象的风格 - 在哪里定义属性? VBA
【发布时间】:2014-04-01 08:26:04
【问题描述】:

我对面向对象的编程很熟悉,并试图让我的风格正确。

我经常有一个对象,其中一个属性是包含其他对象的字典。将其称为包含“玩家”类的“团队”类。

现在假设每次将玩家添加到团队时,我都希望更新团队的平均年龄。

我最喜欢的解决方案:

Sub Main 我应该说只是

 Team.add(Player)

那么在Team 方法add 是:

 Public Sub Add(Player As CPlayer):
      pPlayers.Add Player.Name, Player
      Me.UpDateAvgAge(Player.Age)       
 End Sub

现在我可以想象至少一种替代方法是:

Main:

Team.add(Player)
Team.UpDateAvgAge(Player.Age)

add 方法当然不应该有 Me.UpDateAvgAge(Player.Age) 行。

不用说这只是最简单的例子。在现实生活中,每次我“添加”某些东西时都会“更新”许多属性。

程序员之间是否就如何进行此添加/更新达成共识?有什么指导方针吗?

提前通知!

【问题讨论】:

  • 在平均情况下,我会做的不是在Team 类中有名称为averageAge 的特殊字段,而是添加简单计算的Get AvarageAge 属性(没有背景字段)每次打电话时计算平均年龄。据我所知,此类属性的一般做法(至少在另一种 OOP 语言中)
  • 在这种情况下,您的第一个选项比第二个更好。你不应该让用户干预类的逻辑——所有这些计算都应该隐藏在类实现中
  • 进一步了解 simoco 的第一条评论。几乎所有可计算的财产都应该立即归还。它始终是这样设计的,您不会在变量中存储任何可计算的属性。在基于字典的任何可计算情况下,您迭代字典并将所有Ages 相加,然后将其除以字典中的项目数。
  • 一个原因很简单,如果您在代码中的其他位置使用if birthday then player.Age = player.Age + 1,那么通过迭代您的集合来计算平均值将产生正确的结果,而无需记住更新支持字段。
  • @VBOG 您实际上执行了更多操作,因为您添加到集合中的每个玩家都需要计算平均年龄(1 + 1 *n),但您每次都不需要平均年龄添加一个播放器(b/c 你正在添加一个播放器)。您只需要在请求时知道平均值。您只需迭代集合一次即可检索它,并通过每次添加玩家时计算它来重复执行相同的操作。 OOP 的主要原则之一是DRY Principle。 OOP 解决方案比这个高 3 cmets。

标签: vba excel coding-style custom-object


【解决方案1】:

我可以想象这样的事情。 CTeam 类会在新玩家添加到集合时预先计算团队成员的年龄总和。然后只需使用这个数字,而不必遍历所有项目并计算数字。但是如果成员从集合中删除等情况下,您必须更新值。您必须决定这项工作是否合适,或者您是否只是在需要时计算所有值(意味着没有缓存)。

您也可以将事件添加到 CTeam 类,以便让订阅者知道新的团队成员已添加到集合中。就像在这个例子中,UserForm1 是订阅者,当 CTeam 类的 publischer 创建新播放器时,它会收到通知。高温

' CTeam 类:

Public Event PlayerWasAdded(player As CPlayer)

Private m_players As VBA.Collection
Private m_sumTeamAge As Single

Private Sub Class_Initialize()
    Set m_players = New VBA.Collection
End Sub

Public Sub Add(player As CPlayer)
    m_players.Add player, player.Name
    m_sumTeamAge = m_sumTeamAge + player.Age
    RaiseEvent PlayerWasAdded(player)
End Sub

Public Property Get AverageAge() As Single
    If m_players.Count > 0 Then
        AverageAge = m_sumTeamAge / m_players.Count
    Else
        AverageAge = 0
    End If
End Property

' UserForm1 类:

Private WithEvents m_team As CTeam

Private Sub UserForm_Initialize()
    Dim i As Integer

    Set m_team = New CTeam

    For i = 1 To 5
        m_team.Add CreateNewPlayer(i)
    Next
End Sub

Private Sub m_team_PlayerWasAdded(player As CPlayer)
    MsgBox "New player " & player.Name & " was added. Do something ...", vbInformation
End Sub

Private Sub ShowAverageAge_Click()
    MsgBox "Average age of team member is: " & m_team.AverageAge, vbInformation
End Sub

Private Sub AddNewPlayer_Click()
    m_team.Add CreateNewPlayer(...)
End Sub

Private Function CreateNewPlayer(platerIndex As Integer) As CPlayer
    Dim upperbound As Integer: upperbound = 35
    Dim lowerbound As Integer: lowerbound = 18
    Dim player As CPlayer

    Set player = New CPlayer
    player.Name = "Player_" & platerIndex
    player.Age = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
    Set CreateNewPlayer = player
End Function

【讨论】:

  • 在我的情况下,关键是将平均之类的东西移动到Get 方法。我确实在性能上有所损失(有助于我使用字典),但在代码清晰度和可用性方面获得了很多。
猜你喜欢
  • 1970-01-01
  • 2022-09-27
  • 1970-01-01
  • 2018-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 2011-05-23
相关资源
最近更新 更多