2017-02-26 71 views
2

我有這樣的枚舉:設置的MathContext到BinaryOperator參考方法

public enum Operator { 
    add("+", BigDecimal::add), 
    subtract("-", BigDecimal::subtract), 
    multiply("*", BigDecimal::multiply), 
    divide("/", BigDecimal::divide), 
    mod("%", BigDecimal::remainder); 

    Operator(final String symbol, final BinaryOperator<BigDecimal> operation) { 
     this.symbol = symbol; 
     this.operation = operation; 
    } 

    public BinaryOperator<BigDecimal> getOperation() { 
     return operation; 
    } 
} 

我想用一些MathContext,可以很容易地做到這一點執行這樣的操作時:

MathContext mc = MathContext.DECIMAL32; 
BigDecimal t0 = new BigDecimal(100); 
BigDecimal t1 = new BigDecimal(2); 
BigDecimal result = t0.add(t1, mc); 

但是,如果我想在枚舉中使用對BinaryOperator的引用我看不到給它的方式MathContext

BigDecimal result = enum.getOperation().apply(t0, t1); 

在文檔或適用的方法中,我可以看到任何選項。

+5

創建一個使用具有您需要簽名的功能接口。 –

+0

您也可以使用會使用MathContext和運算符枚舉的輔助類來包裝它。 – hya

+2

@JBNizet BiFunction不會工作,因爲他需要類似TriFunction的東西,因爲有三個參數而不是兩個(BinaryOperator實現BiFunction,區別只是泛型參數都是相同的類型)。 –

回答

3

更容易根據不同的使用情況,您可以保留範圍的自定義功能界面至少爲:

public enum Operator { 
    add("+", BigDecimal::add), 
    subtract("-", BigDecimal::subtract), 
    multiply("*", BigDecimal::multiply), 
    divide("/", BigDecimal::divide), 
    mod("%", BigDecimal::remainder); 

    private interface TriFunc { 
     BigDecimal apply(BigDecimal a, BigDecimal b, MathContext c); 
    } 
    private String symbol; 
    private TriFunc operation; 

    Operator(String symbol, TriFunc operation) { 
     this.symbol = symbol; 
     this.operation = operation; 
    } 

    public BinaryOperator<BigDecimal> getOperation(MathContext c) { 
     return (a, b) -> operation.apply(a, b, c); 
    } 

    // you can also provide a direct method: 
    public BigDecimal apply(BigDecimal a, BigDecimal b, MathContext c) { 
     return operation.apply(a, b, c); 
    } 
} 

所以任何人使用Operator e計數,不必知道內部使用的接口TriFunc的任何內容。 Operator既可以使用,直接像

BigDecimal result = Operator.add 
    .apply(new BigDecimal(100), new BigDecimal(2), MathContext.DECIMAL32); 

或獲取標準BinaryOperator<BigDecimal>

BigDecimal result = Operator.add.getOperation(MathContext.DECIMAL32) 
    .apply(new BigDecimal(100), new BigDecimal(2)); 
+0

啊,好乾淨!謝謝! – imTachu

2

第一種選擇是執行像一個TriFunction<P1, P2, P3, R>和修改代碼如下:

public enum Operator { 
    add("+", (t0, t1, mc) -> t0.add(t1, mc)), 
    subtract("-", (t0, t1, mc) -> t0.subtract(t1, mc)), 
    multiply("*", (t0, t1, mc) -> t0.multiply(t1, mc)), 
    divide("/", (t0, t1, mc) -> t0.divide(t1, mc)), 
    mod("%", (t0, t1, mc) -> t0.remainder(t1, mc)); 

    Operator(final String symbol, final TriFunction<BigDecimal, BigDecimal, MathContext, BigDecimal> operation) { 
     this.symbol = symbol; 
     this.operation = operation; 
    } 

    public BinaryOperator<BigDecimal, BigDecimal, MathContext, BigDecimal> getOperation() { 
     return operation; 
    } 
} 

但是,你必須實現TriFunction自己(或在網上找到它)來使用,因爲Java沒有按從頭開始提供這樣的東西。

一個更簡單的(IMO快速和骯髒)的方式可能是這樣的:

public enum Operator { 
    add("+"), subtract("-"), multiply("*"), divide("/"), mod("%"); 

    // Attributes and constructors 

    public BigDecimal apply(BigDecimal t1, BigDecimal t2, MathContext mc) { 
     switch (this) { 
      case add:  return t1.add(t2, mc); 
      case subtract: return t1.subtract(t2, mc); 
      case multiply: return t1.multiply(t2, mc); 
      case divide: return t1.divide(t2, mc); 
      case mod:  return t1.remainder(t2, mc); 
     } 
     return null; // never reached 
    } 
} 

而且你可以把它甚至

BigDecimal result = enum.apply(t0, t1, mc);