【问题标题】:Setter method in constructor构造函数中的 Setter 方法
【发布时间】:2013-04-16 13:35:57
【问题描述】:

我遇到了一个问题

public class Student{
     private String studentNumber;
     private String studentName;
     private double studentResult;

     public Student (String aNumber, String aName){
         setStudentNumber(aNumber);
         setStudentName(aName);
         setStudentResult(0);
     }
     // The standard getter and setter method are define here.
}

在构造函数中使用 setter 方法的目的是什么?并且使用 setStudentResult(0),我们还需要另一个实例变量吗?

【问题讨论】:

  • 为什么需要另一个实例变量?看起来你有三个 setter 和三个实例变量......虽然 number 存储在字符串中的事实有点令人担忧。
  • @Jon Skeet - 学生编号实际上可能不是数字。就像电话号码一样。
  • @DonRoby:电话号码不是......但根据我的经验,学生号码可能应该是。或者应该叫学生证。
  • 嗯,是的 - 学生证会更好。

标签: java methods constructor setter


【解决方案1】:

在处理sent(您要发送的)值的验证时,您必须使用上述代码实践。
例如,如果您不想允许将任何负数设置为构造函数中的studentNUmber,那么您必须编写一个逻辑来检查构造函数内部或方法内部的数字,具体取决于类是不可变的还是可变的。如果类是可变的,则在方法中写入逻辑,如果类是不可变的,则在构造函数中写入逻辑(在不可变的类中,不允许编写 setter 方法,因为 setter 方法可以改变对象的状态)。
如果你不应用这样的逻辑,那么任何负值都可以设置为studentNumber

此外,当您在其他类中创建了一个对象并且稍后您想要更改它的状态时,setter 方法很有用,例如,您想要更新学生的姓名,如下面给出的示例,

public class Student {
    private String studentNumber;
    private String studentName;
    private double studentResult;
    // The standard getter and setter method are define here.

    public Student(String aNumber, String aName) {
        studentNumber = aNumber;
        studentName =aName;
    }

    public String getStudentNumber() {
        return studentNumber;
    }

    public void setStudentNumber(String studentNumber) {
        this.studentNumber = studentNumber;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public double getStudentResult() {
        return studentResult;
    }

    public void setStudentResult(double studentResult) {
        this.studentResult = studentResult;
    }

    @Override
    public String toString() {
        return "studentNumber:"+studentNumber+", studentName"+studentName+", studentResult"+studentResult;
    }

}

class Test {
    public static void main(String[] args) {
        Student s = new Student("1", "AAA");
        s.setStudentName("BBB"); //we should call this method because of "studentName" is private variable in Student class.
        System.out.println(s);
    }
}

关于setStudentResult,您不需要另一个实例变量,因为它已经在Student 类中声明。相反,您需要在构造函数中向setStudentResult 值添加一个参数。

public Student(String aNumber, String aName, long result) {
        studentNumber = aNumber;
        studentName =aName; 
        studentResult =result;
    }

【讨论】:

  • 我认为Student类被另一个类子类化时会出现问题,因为子类构造函数总是调用超类构造函数。
  • 仅仅说某事不是一个好的做法根本没有帮助。我不同意你的结论,但没有任何解释,很难说出确切的位置。
【解决方案2】:

调用可覆盖的方法是一种反模式,如果 Student 被覆盖,它可能会导致问题。一个好的模式是让 Student 不可变

public class Student{
    private final String studentNumber;
    ...
    public Student (String studentNumber, ...) {
       this.studentNumber = studentNumber;
    ...

【讨论】:

    【解决方案3】:

    您是否在 setter 方法中执行任何业务逻辑。如果是,我想这就是你从构造函数调用 setter 的原因。如果您只是在 setter 中看到实例变量,那么直接设置实例变量是正常的做法。

    public class Student{
    private String studentNumber;
    private String studentName;
    private double studentResult;
    
    public Student (String aNumber, String aName){
    this.studentNumber = aNUmber;
    this.studentName=aName;
    this.studentResult=0;
    }
    

    【讨论】:

      【解决方案4】:

      从构造函数调用方法不是一个好主意。 构造函数用于设置字段的初始值。

      如果您想从构造函数中调用方法并且不希望有人覆盖它。将类声明为 final

      【讨论】:

      • 如果类是可变的,我认为从构造函数调用setter是合理的——这样,如果有任何验证(例如数字不能为负),你只有一个逻辑地方。我同意从构造函数中调用非最终方法是一个坏主意,但设置器本身很容易成为最终方法。
      【解决方案5】:

      通常在构造函数中使用 setter 的原因是您使用相同的验证。然而,自封装是一种反模式。

      更准确地完成您所编写的工作是拥有一个构造对象并调用 set 方法的静态方法。比这更好的是使整个事物不可变。

      【讨论】:

        【解决方案6】:

        如前所述,在构造函数中使用 setter 方法并不是一个好主意,原因有两个:

        1. 子类可以覆盖它们,这可能会使对象处于未被考虑的状态。

        2. setter 方法可以具有您通常不希望在构造函数中使用的功能。

        这样做的原因有两个:

        1. 大多数情况下,如果您在编写构造函数后生成 setter/getter,IDE(例如 eclipse)会自动执行此操作。

        2. 有时,setter 方法也会执行您在使用构造函数进行初始化时想要执行的验证或格式化。在这种情况下,我建议将验证/格式化提取到不同的函数中,并从构造函数和设置器中调用该函数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-02-13
          • 2011-07-10
          • 2017-03-05
          • 2013-07-30
          • 2011-06-21
          • 1970-01-01
          相关资源
          最近更新 更多