2013-10-10 59 views
1

我試圖創建一個計數器,該計數器在達到預設上限時會翻轉,並在達到上限時重置爲其底面值。我已經實現了這個類,它工作得很好。但是,在我的解決方案中,我想試用Java泛型。我想嘗試和擴展我的計數器,以便它不僅使用整數,而是可以使用任何類型的數字。我知道計數器通常只需要使用整數,但我想知道它是否可以完成。使用數字子類的泛型創建滾動計數器

我覺得代碼和下面類似。但是,java.lang.Number沒有獲取/設置其值的「通用」方式。我是否需要創建自己的數字類來啓用此功能?此外,我知道如果我確實得到了這個工作,我需要改變我的等號檢查,以便它們對浮點值有一個錯誤閾值,這或多或少是我int計數器的修改版本,與我想象的一樣仿製藥。

編輯: 它已經建議我走,我存儲整數計數器和保持增值的映射方法,這樣,當我要吐出一個數字,我只是增量值乘我現在的計。但是,我不認爲這會滿足我的確切需求,因爲我不希望每次增加相同數量。這個計數器的主要重點是更多的一種方法來獲得一個固定範圍的數字,當添加或減少時,知道如何處理迴繞。

我想描述它的最好方法(儘管可能不正確)將會像Integer那樣自動處理溢出/下溢。

package com.math; 

public class GenericRolloverCounter<T extends Number> { 

    private T value; 
    private T lowValue; 
    private T highValue; 

    public GenericRolloverCounter(T l_startValue, T l_highValue) { 
     this.lowValue = l_startValue; 
     this.highValue = l_highValue; 
     this.value = l_startValue; 
    } 

    public T getValue() { 
     return value; 
    } 

    public void setValue(T value) { 
     this.value = value; 
    } 

    public void increment(T valToIncrementBy) { 
     this.value += valToIncrementBy; 
     if (this.value > this.highValue) { 
     this.value = (this.lowValue + (this.value - (this.highValue + 1))); 
     } 
    } 

    public void increment() { 
     this.increment(1); 
    } 

    public void decrement(T valToDecrementBy) { 
     this.value -= valToDecrementBy; 
     if (this.value < this.lowValue) { 
     this.value = ((this.value + this.highValue + 1) - this.lowValue); 
     } 
    } 

    public void decrement() { 
     this.decrement(1); 
    } 

    @Override 
    public String toString() { 
     return Integer.toString(this.value); 
    } 
} 
+1

你是什麼意思的任何類型的數字?如果你有一個計數器,它在5.54643643,你期望下一個數字是什麼? – Cruncher

+1

我們使用整數來計算事物是有原因的。因爲整數是可數的。沒有「下一個實數」的概念。有一個下一個雙重的概念,但它是相當隨意的,雙打之間的差距不統一。 – Cruncher

+0

@Cruncher作爲孩子,我們都學會「按5計算」,這表明我們並不總是以單一的整數值計算。例如,我們在美國以.01和.05以及.10和.25爲單位計算貨幣,因爲這就是我們的硬幣被分成美元的方式。我認爲它的下一個雙倍的概念不會像增加和減少一個固定數量或一組數量那樣多。 –

回答

0

您可能需要同時指定由計算量。默認值爲1

你可以通過使用Number方法.doubleValue()和做雙算術來解決其中的一些問題。

這是轉換爲使用此想法的方法之一。

public void decrement(double valToDecrementBy) { 
    double work = this.value.doubleValue(); 
    work -= valToDecrementBy; 
    // should use some value related to incrementing amount 
    if ((this.value.doubleValue() - this.lowValue.doubleValue()) < 0.1D) { 
    work = ((this.value.doubleValue() + this.highValue.doubleValue() + 1) - this.lowValue.doubleValue()); 
    } 
    // ... no way to put it back 
} 

但是,仍然沒有辦法將價值放回來,這是乾淨和容易的。由於「數字」只有少數常用的非抽象子類,因此可以使用一些醜陋的instanceof東西來存儲返回值。這將是這個樣子:

if (theValue instanceof Double) { // depends on it having a non-null value prior 
    theValue = (T)(new Double(work)); 
} 

或者你可以當你開始,只是用雙打工作的出發值轉換爲double

private double value; 
private double lowValue; 
private double highValue; 

public GenericRolloverCounter(T l_startValue, T l_highValue) { 
    this.lowValue = l_startValue.doubleValue(); 
    this.highValue = l_highValue.doubleValue(); 
    this.value = l_startValue.doubleValue(); 
} 

這確實會引入增加浮點值和舍入/評估問題的問題。

哦......和你toString()應該是:

return value.toString(); 

要在T類使用本地toString()方法。

@破碎機的評論提出了另一種方式來做到這一點。將所有內容映射到'int'並保持乘數。這裏有一些代碼來展示我的意思。(謝謝粉碎機)

private int value; 
private int lowValue; 
private int highValue; 
private double incr; 

public GenericRolloverCounter(T l_startValue, T l_highValue, T incrementAmount) { 
    double incr = incrementAmount.doubleValue(); 
    this.lowValue = Math.round(l_startValue.doubleValue()/incr); 
    this.highValue = Math.round(l_highValue.doubleValue()/incr); 
    this.value = Math.round(l_startValue.doubleValue()/incr); 
} 

public void increment(int valToIncrementBy) { 
    this.value += valToIncrementBy; 
    if (this.value > this.highValue) { 
    this.value = (this.lowValue + (this.value - (this.highValue + 1))); 
    } 
} 

@Override 
public String toString() { 
    return String.valueOf(incr * this.value); 
} 
+1

我做了一個編輯,擴展了我想要用這門課做的一件事。感謝您正確使用toString的提示。我可能會嘗試instanceOf的東西,但我認爲最主要的是我讓這個過於複雜,試圖泛化一些不需要的東西。我的意思是希望我們不會很快提出另一種原始數字類型。如果我們這樣做,我認爲還有其他事情要先處理。 – zero298

+0

我打算接受這個答案,因爲確實沒有辦法按照我所說的方式來做到這一點,但這個答案提供了一個有效的選擇。 – zero298