【问题标题】:Is this setter 'evil'这个二传手是“邪恶的”吗
【发布时间】:2009-02-25 20:26:31
【问题描述】:

有很多关于 getter 和 setter 是“邪恶”的讨论。

我的问题是:下面的二传手是邪恶的吗? (为简洁起见,省略了其他类)

int balance

public void deposit(int amount)  
{  
    this.balance += amount;  
}

此类正在模拟 ATM。在英国,有一些 ATM 可以让您存款和取款,因此该对象需要一种更改其状态(余额)的方法。这个二传手是“邪恶的”吗?

【问题讨论】:

  • 这不是二传手。

标签: oop setter


【解决方案1】:

除了不处理异常情况之外,它看起来像一个非常好的 OO 方法 - 它被称为它所做的事情,它按照您的期望做。

【讨论】:

    【解决方案2】:

    我不相信人们谈论 getter 和 setter 时的意思,因为这不仅仅是将成员设置为给定值。

    我不关心 setter 和 getter,但主要是因为我认为我的“对象”是代码库中更高级别的实体。例如。 (IMO)在课堂之外进行操作会“更错误”:

    account.SetBalance(account.GetBalance() + depositAmount)
    

    相反,您在对象中实现了更高级别的功能;你存了一笔钱,然后让对象找出处理它的正确方法。与我上面给出的 getter/setter 示例相比,这允许对异常条件进行更集中的处理。

    【讨论】:

      【解决方案3】:

      这是一个棘手的问题吗?我问是因为提供的方法甚至不是“setter”方法。这是一个操作,而不是一个属性。 Setter 和 Getter 通常是私有变量(属性)的访问器方法。所以我想你的问题的答案是:

      这不是setter,但作为对对象执行操作的通用方法,它一点也不邪恶。

      【讨论】:

        【解决方案4】:

        对于一个类,通过 setter 设置值并没有什么坏处,但这更像是一个函数,而不是直接的 setter。是的,它设置属性的值,但它通过添加而不是替换先前的值来实现,并且名称不对齐。

        真正的“二传手”看起来更像这样:

        int balance
        
        private void setBalance(int amount)
        {
            this.balance = amount;
        }
        
        public void deposit(int amount)  
        {  
            setBalance(this.balance + amount);  
        }
        

        不过,对于您的特定 ATM 问题,我非常怀疑 ATM 是否会立即为您的余额添加存款。它可能需要通过单独的机制收集和发布。

        【讨论】:

        • 现在看起来像二传手邪恶。使用 setter 的一个关键优势是使其成为设置值的用户 API。底层逻辑可以改变,用户代码不受影响。在这个例子中,它是私有的,没有任何设计。
        • 这个实现没有任何收获——但是当他们需要开始记录每一个余额变化时,最好已经强制将所有这些变化放在一个地方。
        • 我同意。但是,这种设计不会影响用户。将代码从私有字段更改为私有 setter 不会更改用户 API,因此它只是一个未使用的抽象层,直到您将日志记录代码放在那里。
        • 我想让我的示例既简单又与原始问题相关,并演示一个真正的二传手。暂时假设隐含了额外的日志记录代码......
        • 另外:我在编写示例时确实考虑过将 setBalance 公开,但考虑到上下文,我无法证明将其作为类公共接口的一部分。
        【解决方案5】:

        就个人而言,我将其称为方法,而不是设置器。典型的二传手是

        public void deposit(int new_balance)
        {
            this.balance = new_balance;
        }
        

        它所做的只是让您直接访问类的内部,从而破坏通过封装它们和限制访问而获得的任何价值。这就是人们不喜欢它们的原因。

        【讨论】:

        • 那么,mutator 方法与 setter 方法不同?
        【解决方案6】:

        好吧,您可能想要检查负金额、零金额等……但只要给出要求就可以了。

        遵循这个经验法则,你创建的每个变量都应该是 final 的,除非它必须改变,并且永远不要为实例变量创建 set 方法,除非你真的希望它们在类之外被改变。

        【讨论】:

          【解决方案7】:

          不一定;您提到您想模仿 ATM(自动取款机)的行为。而且您担心自动取款机可以让您存款和取款。但是这些操作,存款和取款,必须是序列化的。你需要你的所有动作都是原子的,所以这种方法比你尝试做更多事情的方法要好。

          【讨论】:

            【解决方案8】:

            我看到的一个问题是您在处理金钱时使用的是整数类型。如果这是一个定点数,则不是问题,但没有迹象表明它是这样的。

            【讨论】:

              【解决方案9】:

              IMO,ATM 不应将“余额”作为字段。

              (另外,你的 'deposit' 方法不是 setter)

              您可能应该有一个带有“余额”字段的 Account 对象,并且可能有一个方便的方法“modifyBalance”,它采用正值来增加余额或负值来减少余额。

              然后,当执行这些类型的交易时,您的 ATM 方法会在 Account 对象上调用“modifyBalance”。

              【讨论】:

                【解决方案10】:

                你无法判断一个方法是否邪恶,这取决于上下文以及谁可以访问该对象。

                如果您对所有字段都有 getter 和 setter,并且每个人和他的狗都可以访问该对象,那么这是非常糟糕的,因为基本上没有数据封装。

                另一方面,如果您只为需要它的字段设置设置器,并且该对象只为少数需要与其通信的其他对象所知,那么这将是完全可以的。

                【讨论】:

                  【解决方案11】:

                  那不是二传手。这是一个普通的方法(或成员函数,或其他)。

                  setter 是一个将给定变量设置为给定值的函数,通常是个坏主意。方法是执行给定类操作的函数。就类而言,它是有意义的。

                  如果你有一个奇怪的数据结构,你可能实际上没有一个“平衡”变量。无论你的数据结构是什么,你都必须有一个“存款”功能。有部分区别。

                  【讨论】:

                    【解决方案12】:

                    这不是一个setter,它是一个正常的方法

                    即使是二传手,也不是邪恶的

                    这是一个邪恶的二传手

                    int _balance = 0;  
                    public int Balance()  
                    {  
                        get { return _balance; }  
                        set { }    //now that's evil!  
                    }
                    

                    【讨论】:

                      猜你喜欢
                      • 2011-01-02
                      • 1970-01-01
                      • 2011-12-07
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-11-18
                      • 2010-11-26
                      • 2020-08-10
                      相关资源
                      最近更新 更多