[英]question about virtual methods in java
簡單地說:我想要以下代碼打印“sub”:
Element e = new SubElement();
print(e);
...
private static void print(Element e) {
System.out.println("e");
}
private static void print(SubElement e) {
System.out.println("sub");
}
我不想改變印刷品(元素e)。 所以沒什么
private static void print(Element e) {
if (e instanceof SubElement) {
print((SubElement) e);
} else {
System.out.println("e");
}
}
我想做的是
print(e.getClass().cast(e));
自動將其強制轉換為真正的子類並強制系統輸入print(SubElement e)。 這有點可能嗎?
在編譯時選擇運行的重載方法,這就是選擇Element版本而不是SubElement版本的原因。 更合理的是讓Element或子類包含應該打印的數據。
class Element {
public String getName() {
return "e";
}
}
class SubElement extends Element {
public String getName() {
return "sub";
}
}
然后在打印方法中:
private static void print(Element e) {
System.out.println(e.getName());
}
這是否有意義將取決於Element
類實際是什么以及打印數據代表什么。
是。 您可以使用訪客模式 。 但是它適用於穩定的定義良好的層次結構,因為您必須定義的Visitor接口需要每種類型的方法。
interface ElementVisitor {
visit(Element e);
visit(SubElement se);
}
class ElementerPrinter implements ElementVisitor {
visit(Element e) { System.out.println("e"); }
visit(SubElement e) { System.out.println("sub"); }
}
class Element {
// here's the trick, Element knows that this is Element
// and childs have to implement it!
// if the parent-most class is an interface it force you to implement!
accept(ElementVisitor visitor) { visitor.visit(this); }
}
class SubElement {
// here's the trick, Element knows that this is SubElement
accept(ElementVisitor visitor) { visitor.visit(this); }
}
print()
需要成為Element
的實例方法。 你試圖以一種艱難的方式模仿多態。 如果你想這樣做,你無法真正避免從Class
到函數對象的一些if
語句映射。 何必呢?
您是否能夠將行為差異推向元素類?
Element e = new SubElement();
print(e);
...
private static void print(Element e) {
System.out.println(e.getMessageToPrint());
}
// no longer needed
//
//private static void print(SubElement e) {
// System.out.println("sub");
//}
這樣, SubElement
可以覆蓋getMessageToPrint()
方法。
或者更好的是:
Element e = new SubElement();
e.print();
我會選擇不同的方法。 或
基類
public class Element{}
派生類
public class SubElement extends Element{}
輔助界面打印元素
public interface PrintHelper{
void print(Element element);
}
工廠為給定元素獲得最佳PrintHelper
public class PrintHelperFactory{
private final Map<Class<? extends Element>, PrintHelper> registeredHelpers =
new HashMap<Class<? extends Element>, PrintHelper>();
// Register a PrintHelper for a given Element class.
public void registerHelper(final Class<? extends Element> clazz,
final PrintHelper helper){
this.registeredHelpers.put(clazz, helper);
}
// Get the most specific PrintHelper for a given Element.
public PrintHelper getHelperForElement(final Element element){
Class<? extends Element> clazz = element.getClass();
while(!Object.class.equals(clazz)){
if(this.registeredHelpers.containsKey(clazz)){
return this.registeredHelpers.get(clazz);
}
clazz = (Class<? extends Element>) clazz.getSuperclass();
}
return null;
}
}
客戶端測試類,作為Java Application運行
public class Main{
public static void main(final String[] args){
final PrintHelperFactory factory = new PrintHelperFactory();
factory.registerHelper(Element.class, new PrintHelper(){
@Override
public void print(final Element element){
System.out.println("Element");
}
});
factory.registerHelper(SubElement.class, new PrintHelper(){
@Override
public void print(final Element element){
System.out.println("Sub Element");
}
});
// test it with an Element
final Element elem = new Element();
factory.getHelperForElement(elem).print(elem);
// test it with a sub class
final Element sub = new SubElement();
factory.getHelperForElement(sub).print(sub);
}
}
產量
Element
Sub Element
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.