0

我被困在試圖弄清楚如何使用泛型來檢查超類的給定對象是否是來自此超類的子類之一的子類的期望對象。讓我舉一個例子:泛型和類型安全:檢查參數的動態綁定

比方說,我們有一個層次結構:

public interface Expression{ 
    public Object evaluate(); 
} 

public abstract class BooleanExpression implements Expression{ 
    public abstract Boolean evaluate(); 
} 

public abstract class PositionExpression implements Expression{ 
    public abstract Integer[] evaluate(); 
} 

public class Conjunction extends BooleanExpression{ 
    public Boolean evaluate() 
} 

public class BooleanTrue extends BooleanExpression{ 
    @Override 
    public Boolean evaluate(){ 
     return true; 
    } 
} 

現在,我的觀點是,該計劃應只能夠當且僅當在給定的參數來構造一個對象從連詞該構造函數是一個BooleanExpression或此類的一個子類。

我曾嘗試使用泛型這樣的:

public class Conjunction<T extends BooleanExpression> extends BooleanExpression{ 
    public Conjuction(T left, T right){ 
     this.left = left; 
     this.right = right; 
    } 

    private T left, right; 

    @Override 
    public Boolean evaluate(){ 
     return (left.evaluate() && right.evaluate()) 
    } 

當我想創建一個實例,我有以下代碼:

public Expression createConjunction(Expression left, Expression right){ 
    return new Conjunction<BooleanExpression>(left, right) 
} 

但不幸的是,這並不編譯!我想使用泛型來檢查leftright是否爲BooleanExpression的實例,因爲Conjunction只能在兩個布爾值之間(而不是PositionExpression)。 然而,leftright可以是不同的BooleanExpressionleft可以是Conjunctionright可以是BooleanTrue(作爲示例)。

所以,我想要創建一個Conjunction的實例,當兩個給定的參數leftright都是BooleanExpression的子類時。 創建一個Conjuction的實例,其中一個參數是PositionExpression的子類不應被編譯器接受。

我想在不改變createConjunction方法和使用泛型類/接口的情況下解決此問題。有任何想法嗎?

+0

你一定要改變'createConjunction'函數,因爲在它的當前形式下它是無效的。所有你應該改變的是使'左'和'右'布爾表達式'而不是'表達式'的類型。 – luk2302

+0

編譯器正在做它應該做的事情。它不會編譯,因爲'left'和'right'是'Expression's,但是'Conjuction'構造函數明確要求它們是'BooleanExpression'的子類。 – Casey

+0

@Casey我猜編譯器沒有辦法檢查'left'的底層對象是否是子類'BooleanExpression',是嗎? (例如,當我調用這個方法'createConjunction'時,'left'參數可以包含'BooleanTrue',它是'BooleanExpression'的子類(它實現'Expression'接口)) –

回答

1
public Expression createConjunction(Expression left, Expression right){ 
    return new Conjunction<BooleanExpression>(left, right) 
} 
上述方法

,您要求2個expression對象,但在 conjuction構造它要求延伸Booleanexpressions這就是你所得到的編譯錯誤部分2級的對象。

你可以改變你createConjuction方法

public Expression createConjunction(BooleanExpression left, BooleanExpression right){ 
     return new Conjunction<BooleanExpression>(left, right) 
    } 

,或者你可以在conjuction類改變generic表達

Conjunction<T extends Expression> extends BooleanExpression{} 
0

如果你想保持createConjunction方法和Don」的簽名我想要改變Conjunction類,那麼你可以在createConjunction方法中檢查並轉換參數的類型。

public Expression createConjunction(Expression left, Expression right){ 
    if(!(left instanceof BooleanExpression) || !(right instanceof BooleanExpression)){ 
     throw new IllegalArgumentException("wrong expression arguments, BooleanExpression expected"); 
    } 
    BooleanExpression _left = (BooleanExpression)left; 
    BooleanExpression _right = (BooleanExpression)right; 
    return new Conjunction<BooleanExpression>(_left, _right); 
}