【问题标题】:Java Overriding Protected Setters and Eliminate Public SettersJava 覆盖受保护的设置器并消除公共设置器
【发布时间】:2015-01-04 17:58:57
【问题描述】:

人物类:

public class Person {


    private String firstName;
    private String lastName;

    public Person(String firstname,String lastname) throws InvalidDataException
    {
        setFirstname( firstname);
        setLastname(lastname);
    }


    public void personFirstName(String firstName) throws InvalidDataException { 
        setFirstname(firstName);
    }

    public void personLastName(String lastname) throws InvalidDataException {

        setLastname(lastname);
    }

    public String getFirstName() {
        return firstName;
    }

    public String getlasttName()
    {
        return lastName;
    }

    protected final void setFirstname(String firstname) throws InvalidDataException{
         if( firstname == null ||firstname.length() < 1) {
                throw new InvalidDataException("First Name Cannot be Empty");
         }
          this.firstName=firstname; 

    }

    protected final void setLastname(String lastname) throws InvalidDataException {

         if( lastname == null ||lastname.length() < 1) {
                throw new InvalidDataException("Last Name Cannot be Empty");

         }

         this.lastName = lastname;
    }



}

教授级:

public class Professor extends Person {


    private String  professorID;



    public Professor(String professorID,String firstname, String lastname) throws InvalidDataException {
        super(firstname, lastname);
        // TODO Auto-generated constructor stub
        setProfessorID(professorID);
    }

    public void setID(String professorID) throws InvalidDataException{

        setProfessorID(professorID);
    }

    public String getID()
    {
        return this.professorID;
    }

    private void setProfessorID(String ID) throws InvalidDataException{
         if( ID == null ||ID.length() < 1) {
                throw new InvalidDataException("ID Cannot be Empty");
         }
          this.professorID=ID; 

    }

    public void printData()
    {
         System.out.println("Professor ID: " + this.getID() + " First Name: " + this.getFirstName() + " Last Name: " + this.getlasttName());
    }

}

我对实现 setter 并在我的子类中调用它们进行了一些研究。通过将它们声明为受保护的和最终的,我可以防止子类覆盖它并执行不需要的行为。我的问题是,我现在可以摆脱 personFirstName()personLastName() 吗?我的构造函数不使用它,它们调用受保护的 final setFirstnamesetLastname()。摆脱 public setter 会在以后的开发中引起问题吗?

【问题讨论】:

  • @T.J.Crowder - 你会建议删除 setFirstName() 吗?我的问题是,如果我这样做,以后会造成问题吗?
  • @T.J.Crowder - 我在其他地方读到过,这样做是不可取的。因为我在构造函数中调用了setter,并且我读到不建议使用可以覆盖的方法调用构造函数。
  • 啊,好吧,关键是要避免从构造函数调用可能被覆盖的方法。我理解了。 :-)

标签: java inheritance polymorphism


【解决方案1】:

您说过您的目标是避免在构造函数中调用可能被子类覆盖的方法。如果是这样,我会这样处理:

public Person(String firstName, String lastName) {
    this.privateSetFirstName(firstName);
    this.privateSetLastName(lastName);
}
private void privateSetFirstName(String firstName) {
    // ...your logic for setting the field...
}
private void privateSetLastName(String lastName) {
    // ...your logic for setting the field...
}
public void setFirstName(String firstName) {
    this.privateSetFirstName(firstName);
}
public void setLastName(String lastName) {
    this.privateSetLastName(lastName);
}

例如,使标准制定者成为标准,并将特定于实现的细节保存在实现中的私有方法中。

【讨论】:

  • 谢谢。我遵循这里给出的建议。 stackoverflow.com/questions/12410338/….
  • @CharlesWhitfield:是的,你一说,我就明白了。 :-)
  • @T.J. Crowder - 如果我想与我的子类共享私有方法,我可以将它们声明为受保护的和最终的,正确的(就像我在上面的示例中所做的那样)?
  • @CharlesWhitfield:当然可以,但我的直觉是不会。它们是您班级中的实现细节。子类设置这些字段的唯一正确方法应该是通过基本构造函数和setFirstName/setLastName
  • 非常感谢。还有一个问题,我实现它的方式是我的例子,这不是我们想要的方式吗?还是太乱了?
【解决方案2】:

你应该尽量避免在 getter 和 setter 中做事,这会让你很难追踪错误 - 检查其他地方的数据。我认为这个更简单的版本可以:

public class Person {

    private String firstName;
    private String lastName;

    public Person() {} // introducing an empty constructor gives you more flexibility


    public Person(String firstname, String lastname) {
        setFirstname( firstname);
        setLastname(lastname);
    }

    public String getFirstName() {
        return firstName;
    } 

    public String getLasttName() {
        return lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

public class Professor extends Person {

    private String  professorID;

    public Professor (super();) {} // introducing an empty constructor gives you more flexibility

    public Professor (String firstname, String lastname, String professorID) {
        super(firstname, lastname);
        this.professorID = professorID;
    }

    public void setID(String professorID) {
        setProfessorID(professorID);
    }

    public String getID() {
        return this.professorID;
    }
}

【讨论】:

  • 我已经习惯了按照您展示的方式进行操作。但是,当我在被指示不要那样写之前发布我的代码时。此外,实现无参数构造函数意味着可以创建公正的对象。
  • “你应该尽量避免在 getter 和 setter 中做事......” setter 中的基本检查是完全正常和适当的。
  • 在某些情况下,例如在休眠实体中,具有空构造函数甚至是强制性的:stackoverflow.com/questions/2935826/…
  • @Journeycorner: 是否实现零参数构造函数完全是根据具体情况而定。是的,某些实体框架需要它们。这并不意味着你应该总是写它们。有状态的对象不应该有无效的状态;如果构造函数中的 args 是防止无效状态所必需的,那么构造函数中的 args 是必需的。如果一个框架要求你通过零参数构造函数来拥有潜在无效的对象,你只需屈服于实现的必要性并尽可能地控制损害。
  • @T.J.Crowder:我同意,我们不知道上下文,所以没有灵丹妙药。但是看起来他的类代表某种模型,如果遇到调用 getter 后抛出异常的模型,我会感到非常惊讶。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 2013-06-19
  • 2011-11-25
  • 2012-01-26
相关资源
最近更新 更多