[英]In Java, how do I refer explicitly to a static member of the class of `this`?
在Java中,如何顯式引用this
的靜態成員?
我想明確地引用靜態成員以獲得可讀性,但是不要使用文字類名來尊重重寫該值的子類。
一個人為的例子:
class Flying {
static final String label = "A Flying Superhero";
String exclamation() {
return "Look! Up in the sky! It’s a bird! It’s a plane! It’s "+(WHAT GOES HERE?)+"!";
}
}
class Superman extends Flying {
static final String label = "Superman";
}
class Howard extends Flying {
static final String label = "Howard the Duck";
}
請注意,我想避免單獨使用label
,因為它的含義可能不明確; 我希望讀者立即知道它是一個靜態成員,就像他們從Flying.label
,但沒有命名基類。
(在激發這個問題的情況下,靜態成員也是最終的,但我認為這不會影響你如何引用它。)
編輯 :這是一個可能更具說服力的案例。 我想在超類中實現main
,並讓它創建並使用被調用的子類的實例。
class Super
public static void main( String[] args ) {
Super instance = new (?WHAT GOES HERE?)( /*...*/ );
instance.use();
}
}
class Sub extends Super {
void use() {
/* ... */
}
}
當在Sub
上啟動jvm時,我希望它使用相同的main實現,但是使用子類的實例。
這種情況的不同之處在於上下文是靜態的,要訪問的靜態成員是構造函數。
(這是在建模和模擬的研究生課程中進行的家庭作業;超類是一個模型,不同的場景被實現為子類。)
為了澄清這個問題 ,我認為需要做三件事:
aClass.getDeclaredField
?) aClass.getConstructors
?) 結論
在讀到答案之前,我沒有意識到我試圖做一些與Java方式相反的事情。 顯然我已經習慣了更多動態語言。 (感覺我被JavaScript寵壞了似乎是錯誤的。)
這個架構主要是由我正在使用的框架提供的GUI激發的,它為您提供了一個類選擇器,然后是一個UI,用於與您選擇的類的實例進行交互。 這使得使用不同場景的便捷方式可以為每個場景創建一個類。
對於僅限於訪問靜態成員的原始情況,暫時使用文字類名稱就足夠了。
對於涉及實例化的編輯案例,我將實例化留在子類中並將實例傳遞給超類的方法,如下所示:
class Model {
public static void run( Model m ) {
/* ... */
}
}
class Scenario extends Model {
public static void main( String[] args ) {
Model.run( new Scenario( /*...*/ ) );
}
}
將來,我會盡量避免將某些圖書館引入與語言功能沖突的領域。
你不能覆蓋變量,相反,你需要提供一個方法,例如......
class Flying {
private final String label = "A Flying Superhero";
String exclamation() {
return "Look! Up in the sky! It’s a bird! It’s a plane! It’s " + getLabel() + "!";
}
public String getLabel() {
return label;
}
}
class Superman extends Flying {
private final String label = "Superman";
@Override
public String getLabel() {
return label;
}
}
class Howard extends Flying {
private final String label = "Howard the Duck";
@Override
public String getLabel() {
return label;
}
}
子類不繼承靜態成員。 在你的新例子中, main
可以像Sub.main(args);
一樣被Sub Sub.main(args);
但它總是屬於Super
。 您甚至可以檢查堆棧跟蹤,確認它是否在Super
上調用。
這是不可能做到的。
aClass.getDeclaredField
?) 這可以做到,但如果你只使用常規繼承,那么解決一個非常簡單的問題是一種非常麻煩的方法。
aClass.getConstructors
?) 這可以做到並且不時有用。 現在使用Java 8 Supplier不太有用,例如SomeClass::new
。
靜態是在Java中處理這種問題的錯誤方法。 常規繼承可以讓您輕松地完成這些工作。
class InterfacesExample {
public static void main(String[] args) {
@SuppressWarnings("unchecked") // Arrays#asList
List<Class<? extends Printer>> classes = Arrays.asList(
FruitPrinter.class,
TreePrinter.class
);
for(Class<? extends Printer> cls : classes) {
try {
Constructor<? extends Printer> ctor = cls.getDeclaredConstructor();
Printer p = ctor.newInstance();
p.print();
} catch(Exception e) {
System.err.println(e);
}
}
}
}
interface Printer {
void print();
}
class FruitPrinter implements Printer {
@Override
public void print() {
System.out.println("Apple, Banana, Plum, Pear");
}
}
class TreePrinter implements Printer {
@Override
public void print() {
System.out.println("Oak, Maple, Elm, Willow");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.