创建后不应更改属性

时间:2017-06-12 23:10:58

标签: java oop inheritance encapsulation

考虑到问题 - "所有游戏对象都提供外部代码获取其大小的能力。但是,它们无法在创建后更改其大小。"

如果我有一个包含私有字段的父类,例如此GameObject类:

public abstract class GameObject {
     private int size;

     public void setSize(int size) {
          this.size = size;
     }
}

以及

等儿童课程
public class Dinosaur extends GameObject {
     public Dinosaur() {
           this.setSize(100);
     }
}

public class Jeep extends GameObject {
     public Jeep() {
          this.setSize(10);
     }
 }      

如何确保在创建对象后不更改大小? 我很困惑,因为如果我将setter方法设置为private,那么我就无法在创建时单独设置每个GameObject的大小。

编辑:为了清晰起见,添加了第二个子类。

5 个答案:

答案 0 :(得分:2)

如果您需要使size变量不可更改,那么您应该使用final修饰符。 有两种方法可以为这种变量设置值:1)构造函数2)内联。只要您希望在每个对象的客户端代码中设置自定义值,就应该使用构造函数:

public abstract class GameObject {

     private final int size;

     public GameObject(int size) {
         this.size = size;
     }
}

public Dinosaur extends GameObject {

   pubilc Dinosaur(int size){
       super(size);
   }
}

在这种情况下,没有必要使用setter方法。

答案 1 :(得分:1)

size可以是final,并在构造函数中传递大小值。你也不需要一个二传手。你只能做必要的吸气剂。

public abstract class GameObject {
    private final int size;

    public GameObject(int size) {
        this.size = size;
    }

     public int getSize() {
         return this.size;
     }
}

答案 2 :(得分:1)

他们的代码有些问题。

首先,如果班级不能在创建后设置大小,为什么要首先提供一个setter?

其次,子类可以覆盖method类中的setSize abstract并执行任何操作。如果您希望inheritance执行此操作:

public abstract class GameObject {

    private final size;

    public GameObject(int size){
        this.size = size;
    }
}

public class Dinosaur extends GameObject {

    public Dinosaur(int size){
        super(size)
    }
}

不提供制定者,并且必须在施工时提供尺寸。如果您想要一个方法来执行此操作,请创建方法final。像这样:

public final setSize(int size){
   this.size = size;
}

通过使它成为final,除了方法之外,子类必须没有覆盖。

另一种方法是,创建此类immutable。您没有使用setters,但您可以拥有getters,并且该类将被设为final,因此不会进行子类化。

public final Dinosaur {

   private final int size;

   pubilc Dinosaur(int size){
       this.size = size;
   }

   public int getSize(){
       return this.size;
   }
}

答案 3 :(得分:0)

(注意:我假设您打算Dinosaur延长GameObject。)

您可以覆盖setSize()方法并抛出异常:

public class Dinosaur extends GameObject {
    ...

    @Override
    public void setSize(int size) {
        throw new UnsupportedOperationException("can't change dinosaur size");
    }
}

答案 4 :(得分:0)

  

考虑到问题 - "所有游戏对象都提供了这样的能力   外部代码来获取它们的大小。但是,他们没有提供   能够在创建后更改其大小。"

这样做的通常方法是让父类的构造函数接受一个size参数。此参数设置不可变大小字段的值。子类可以轻松访问此值,但一旦设置它们就无法更改它。这是满足所列要求的最面向对象的方式。

例如:

public abstract class GameObject {
    private final int size;

    public GameObject(int size) {
        this.size = size;
    }

    public int size() { return this.size; }
    :
    :
}

和一个儿童班:

public class Dinosaur extends GameObject {

    public Dinosaur() {
        super(100);
    }
    :
    :
}

虽然在这个帖子中有一些关于子类如何动态改变大小字段的讨论,但是更好的设计是使用像这里介绍的那样的不可变设计,并且如果需要,客户端代码请求具有不同大小的新对象(比方说,使用copyOf()方法)。不可变设计比可变设计有几个优点,通常是计划价值类时的方法。