[英]Restrict mutable object inside immutable object Java
I am learning about immutable Objects. 我正在学习不可变的对象。 I am trying this code
我正在尝试这段代码
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I want to restrict the calling class from changing the value of name variable of NormalObject 我想限制调用类更改NormalObject的name变量的值
But the following code changes the value 但是以下代码更改了值
ImmutableObject obj = new ImmutableObject("Siddle");
System.out.println(obj.getObj().getName()); //prints Siddle
obj.getObj().setName("Kelly");
System.out.println(obj.getObj().getName()); //prints Kelly
How to restrict it? 如何限制它?
For an object to be immutable, all of its properties must be immutable. 对于不可变的对象,其所有属性必须是不可变的。 Its state must not be changeable.
它的状态一定不可改变。
To do that, you have to put an immutable facade on NormalObject
, you can't directly return a NormalObject
. 要做到这一点,你必须在
NormalObject
上放置一个不可变的Facade,你不能直接返回一个NormalObject
。 The method that returns it will also need a different return type, you can't return NormalObject
but actually return something that doesn't behave like a NormalObject
. 返回它的方法也需要一个不同的返回类型,你不能返回
NormalObject
但实际上返回的行为不像NormalObject
。
Eg: 例如:
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
private final ImmutableNormalObject objFacade = new ImmutableNormalObject(obj);
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public ImmutableNormalObject getObj() {
return objFacade;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ImmutableNormalObject {
private NormalObject obj;
public ImmutableNormalObject(Normalobject o) {
this.obj = o;
}
public String getName() {
return obj.getName();
}
}
Alternately, if it's acceptable to copy the object and it has a copy constructor (or you can add one), you could do that, but copy-and-return is expensive. 或者,如果复制对象并且它有一个复制构造函数(或者你可以添加一个)是可以接受的,那么你可以这样做,但复制和返回是很昂贵的。
You can do this by returning a copy of your normalObject
in getter: 您可以通过在getter中返回
normalObject
的副本来完成此操作:
public NormalObject getObj() {
return new NormalObject(obj.getName());
// or you can make a copy constructor:
// return new NormalObject(obj);
}
Or you can make a wrapper for your NormalObject
that ignores name setter, but it brakes logic. 或者您可以为
NormalObject
创建一个忽略名称设置器的包装器,但它会制动逻辑。
Please change Your NormalObject code to 请将您的NormalObject代码更改为
public final class ImmutableObject {
private final String name;
// initialise it to null
private final NormalObject obj = null;
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
// use the Constructor for setting name only once during initialization of ImmutableObject via its constructor
obj = new NormalObject(name);
//obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
NormalObject Class NormalObject类
public class NormalObject {
private String name;
public NormalObject(name){
this.name = name;
}
public String getName() {
return name;
}
//Remove any setter on NormalObject
/*public void setName(String name) {
this.name = name;
}*/
}
In an immutable object, if a User tries to change the state of the Object. 在不可变对象中,如果用户尝试更改Object的状态。 either you won't allow or return a new Instance of the Immutable class.
要么你不允许或返回一个新的Immutable类实例。
So, since Date is a mutable class. 所以,因为Date是一个可变类。 You can create an immutable wrapper around date, and you can expose only those methods, that are subject to be used in your Immutable-Date's perspective, but you return a new instance of your Immutable class, with the changed attribute of your new Date.
您可以在日期周围创建一个不可变的包装器,并且您只能公开那些可以在Immutable-Date的透视图中使用的方法,但是您返回一个新的Immutable类实例,其中包含新Date的已更改属性。
I don't think final would be required for Immutable variable, because it is already private and Immutable. 我不认为Immutable变量需要final,因为它已经是private和Immutable。
Example : 示例:
public class Main{
private ImmutableDate immutableDate;
public Main() {
this.immutableDate = new ImmutableDate(new Date());
}
public Main(Date date){
this.immutableDate = new ImmutableDate(date);
}
public ImmutableDate getDate() {
return immutableDate;
}
public class ImmutableDate{
// private constructor, so this can only be instantiated within the outer class
// therefore, final keyword not required for Date, as no access given to the variable
private Date date;
private ImmutableDate(Date date) {
this.date = date;
}
// Example methods from Date, that are required for our Immutable implementation
public Main setTime(long time){
Date date1 = new Date();
date1.setTime(time);
return new Main(date1);
}
@Override
public String toString() {
return date.toString();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.