2016-01-21 54 views
0

我創建了Either<A,B>類來表示總和類型。每個實例包裝AB。這由擴展Left<A>Right<B>表示。這些類型對用戶是隱藏的,僅用於存儲對AB的引用,並在Either中實現抽象方法。下面的代碼的相關部分:IntelliJ爲Java類創建自定義警告

/** 
* A simple SumType implementation. Allows the creation of the Sum Type 
* A + B. Every instance of Either is either (haha.. tomatoes, rocks) 
* an instance of Left, with a value of type A, or an instance of Right, 
* with a value of type B. 
* <br><br> 
* The types and constructors for Left and Right are not exposed. 
* Instead, to construct new instance of Left and Right, the createLeft and createRight 
* methods of class Either should be used. 
* <br><br> 
* The types can be the same, but in that case there isn't much use to using Either. 
* 
* @param <A> The first type to sum 
* @param <B> The second type to sum 
* @author Mshnik 
*/ 
public abstract class Either<A, B> { 

    private final boolean isLeft; 

    /** 
    * Constructs a new Either 
    * 
    * @param isLeft - true if this is a Left, false if this is a Right 
    */ 
    Either(boolean isLeft) { 
    this.isLeft = isLeft; 
    } 

    /** Creates a Either instance of the given A */ 
    public static <A, B> Either<A, B> createLeft(A a) { 
    return new Left<>(a); 
    } 

    /** Creates a Either instance of the given B */ 
    public static <A, B> Either<A, B> createRight(B b) { 
    return new Right<>(b); 
    } 

    /** 
    * Returns true if this is a Left, false if this is a Right 
    */ 
    public boolean isLeft() { 
    return isLeft; 
    } 

    /** 
    * Returns the value of this Either as an an instance of A. 
    * If the wrapped value is an instance of B, throws a RuntimeException 
    */ 
    public A asLeft() { 
    if (isLeft()) 
     return ((Left<A,B>)this).getVal(); 
    throw new RuntimeException(); 
    } 

    /** 
    * Returns the value of this Either as an an instance of B. 
    * If the wrapped value is an instance of A, throws a RuntimeException 
    */ 
    public B asRight() { 
    if (!isLeft()) 
     return ((Right<A,B>)this).getVal(); 
    throw new RuntimeException(); 
    } 

    /** 
    * Returns the Object stored within this Either. 
    * Should have a stricter type bound (A or B) when implemented by subclasses. 
    */ 
    public abstract Object getVal(); 

    /** 
    * Returns the type of the Object stored within this Either 
    */ 
    public abstract Class<?> getType(); 

    /** 
    * Two Eithers are equal iff: 
    * <br>- They are both Left or both Right, the only two direct subclasses 
    * <br>- The objects they store are equivalent using Objects.equals. 
    */ 
    @Override 
    public boolean equals(Object o) { 
    if(this == o) return true; 
    if(o == null) return false; 
    try { 
     @SuppressWarnings("unchecked") 
     Either<A, B> e = (Either<A, B>) o; 
     return (!(isLeft^e.isLeft)) && Objects.equals(getVal(), e.getVal()); 
    } catch (ClassCastException e) { 
     return false; 
    } 
    } 

    /** 
    * Hashes an either based on the value it stores. 
    * This maintains the hash invariant (two equal objects have the same hashcode), 
    * but is not a perfect hashcode because a Left(a) and Right(a) will have the 
    * same hashcode but are not equivalent. 
    */ 
    @Override 
    public int hashCode() { 
    return Objects.hashCode(getVal()); 
    } 

} 

打算利用asLeft()asRight()簡單,看起來像這樣:

Either<A,B> e = ....; //Take an either reference 
if(e.isLeft()) { 
    A a = e.asLeft(); 
    //Handle a 
} else { 
    B b = e.asRight(); 
    //Handle b 
} 

而且一直是非常有用的在我的項目的其餘部分。

現在我的問題 - 我主要使用IntelliJ(並喜歡它),並且已經注意到它有一個功能,可以阻止你做可能是錯誤的事情,比如將字符串與==進行比較。

Warning generated by IntelliJ when comparing strings with ==

是否有可能創建這樣一個自定義警告我Either類,這樣調用Either::asLeft()沒有檢查Either::isLeft()會生成一個警告?假設IntelliJ(社區版)具有自定義警告功能,它是否允許這種複雜性?

回答

0

是的,這在理論上可以通過開發插件來實現。然而,在實踐中,我建議不要這樣做,因爲實施這種檢查可能需要很多努力。但是,可以通過更改類來使用IntelliJ的空檢查,並創建一個方法getLeftOrNull(),該方法將被標記爲@Nullable,並且將返回null而不是拋出異常。然後IntelliJ會提醒你,如果你沒有在提取它之前檢查null。

另一種選擇是用java 8可選並創建一個方法getLeftOptional()這將包裹的返回值,並迫使呼叫者來處理的情況下,當它是空的(即在EitherRight)。