這是一個奇怪的問題,一成不變的,但可變的,私營部門,而是公共...正確的方法應該是讓他們保護,因爲大家都在說。
不管怎樣,在Java中,你可以使用下三濫的手段,如果安全管理不抱怨,檢查了這一點:
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Priv
{
public static class A
{
private final int x;
public A(int x)
{
this.x = x;
}
}
public static class B extends A
{
public B(int x)
{
super(x);
}
public void setX(int x)
{
Class c = A.class;
try
{
Field f = c.getDeclaredField("x");
f.setAccessible(true);
f.set(this, x);
} catch (IllegalArgumentException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchFieldException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int getX()
{
int v = 0;
try {
Class c = A.class;
Field f = c.getDeclaredField("x");
f.setAccessible(true);
v = f.getInt(this);
} catch (IllegalArgumentException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchFieldException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(Priv.class.getName()).log(Level.SEVERE, null, ex);
}
return v;
}
}
public static void main(String[] args)
{
B b = new B(5);
System.out.println("b.x is " + b.getX());
b.setX(42);
System.out.println("b.x now is " + b.getX());
}
}
如果'A'的合同是不可變的,而'B'擴展了'A',那麼'B' **必須是不可變的。否則,你打破了「是一個」的承諾。代碼可以對'B'對象具有'A'類型的引用,並且儘管'A'是不可變的,發現對象發生了變化。不好。 :-) –
我認爲這裏有一個設計問題。你所說的是x和y是最終的(不可變的),所以改變它們有什麼意義呢?如果你想在一個子類中改變它們,這甚至是最糟糕的:如果一個子類需要改變父類的不可變值,那就不是合適的子類。 –
@NaN:我想你只是用一種讓它看起來比實際更復雜的方式來表達它。看看這些評論,你*不需要*''和'y'在'A'中是不可變的,你只需要'A'不要有任何setter。這裏有一個區別(根據「A」提供的合同)。如果'B'可以修改從'A'繼承的'x'和'y',那麼MeNoMore的答案是正確的。 –