2015-03-10 13 views
14

Trong ứng dụng của tôi, tất cả các số BigDecimal được chia tỷ lệ thành hai chữ số thập phân. Nói cách khác, mỗi khi tôi tạo một BigDecimal mới trong mã của mình, tôi cũng cần sử dụng thang phương pháp:Tạo một kiểu BigDecimal tùy chỉnh

BigDecimal x = BigDecimal.ZERO; 
x.setScale(2, RoundingMode.HALF_UP); 

Vì vậy, để giảm thiểu tác phẩm, tôi muốn tạo ra tùy chỉnh BigDecimal loại của tôi, một cái gì đó như:

public class CustomBigDecimal extends BigDecimal { 

    public CustomBigDecimal(String val) { 
     super(val); 
     this.setScale(2, RoundingMode.HALF_UP); 
    } 

} 

tôi biết this.setScale(2, RoundingMode.HALF_UP); không thực hiện công việc, nhưng tôi không thể tìm ra cách để làm nó, là nó có thể?

+4

Tại sao không sử dụng một loại tùy chỉnh mà các đại biểu đến BigDecimal? – keuleJ

+3

Xin lưu ý rằng 'x.setScale' không thay đổi tỷ lệ' x', nhưng trả về một đối tượng BigDecimal mới có cùng giá trị (có thể làm tròn) và tỷ lệ 2. Bạn phải gán giá trị này cho biến để có hiệu lực. –

Trả lời

5

Bạn có thể tạo CustomBigDecimal kéo dài từ BigDecimal. Tuy nhiên, vì BigDecimal là không thay đổi, bạn sẽ không bao giờ kế thừa trạng thái (chẳng hạn như tỷ lệ và chế độ làm tròn) từ lớp cha.

Tôi muốn đi đến lớp tiện ích được đề xuất trong câu trả lời khác hoặc có thể là trình bao bọc ủy nhiệm mọi hoạt động với một phiên bản BigDecimal thực tế. Nhược điểm của phương pháp này là thương hiệu mới CustomBigDecimal của bạn sẽ không phải là BigDecimal, vì vậy chúng sẽ không thể thay thế được.

EDIT: một nhược điểm của phương pháp này là bạn phải ủy quyền khoảng 50 phương pháp. Không phải là ngày tận thế với một IDE tốt, nhưng chắc chắn không phải là rất hấp dẫn ...

Nếu, sau khi tất cả, bạn vẫn muốn làm CustomBigDecimal kế thừa từ BigDecimal, bạn sẽ cần phải sử dụng một cách tiếp cậntrang trí:

public class CustomBigDecimal extends BigDecimal { 

    private final BigDecimal value; 

    private CustomBigDecimal(BigDecimal value) { 
     super(value.toPlainString()); // needed to compile, 
             // useless except for implicit null-check 
     this.value = value; 
    } 

    public CustomBigDecimal(String val) { 
     this(new BigDecimal(val).setScale(2, RoundingMode.HALF_UP)); 
    } 

    @Override 
    public CustomBigDecimal abs() { 
     return new CustomBigDecimal(this.value.abs()); 
    } 

    // TODO all other methods 

} 
+1

Cảm ơn bạn đã trả lời! Mặc dù tôi đã chọn Danilo Gomes trả lời để thực hiện trong ứng dụng của tôi, tôi sẽ đặt cái này là chính xác vì nó trả lời câu hỏi gốc. Nhờ @MarcusWidegren kể từ khi ông đề nghị phương pháp này quá trong một trong những ý kiến ​​của mình. – yat0

+1

@polska Nhờ bạn! Tôi cũng tin rằng câu trả lời của Danilo là tốt hơn so với cách tiếp cận này, mặc dù tôi sẽ không sử dụng phần singleton. Tuy nhiên, tôi nghĩ rằng cách tiếp cận @Marcus 'là tốt nhất của tất cả vì bạn không cần phải sử dụng một bối cảnh mỗi khi bạn tạo một 'BigDecimal' mới. Điều gì sẽ xảy ra nếu bạn hoặc một nhà phát triển khác quên gửi đối số ngữ cảnh? –

+1

Hmm .. Bạn nói đúng, chúng tôi thực sự là 2, và tôi nghĩ nó sẽ đẹp hơn rất nhiều nếu nhà phát triển khác tiếp tục tạo BigDecimal như bình thường (không có ngữ cảnh), nó trực quan hơn và nó đơn giản hơn ! Cảm ơn :) – yat0

15

Bạn có thể chỉ cần tạo phương thức cho chính mình để tạo BigDecimal bằng 0. Một cái gì đó như:

public static BigDecimal scaled(String val) { 
    BigDecimal x = new BigDecimal(val); 
    return x.setScale(2, RoundingMode.HALF_UP); 
} 

Đặt nó trong lớp trợ giúp, như BigDecimalHelper, BigDecimalFactory hoặc bất kỳ thứ gì. :)

EDIT: Đã thay đổi nó một chút để trả về kết quả của setScale, vì BigDecimal không thay đổi. Và để trả lời thêm câu hỏi ban đầu: không có gì bạn đã viết là không thể vì trạng thái của đối tượng không thay đổi với setScale().

+0

Số không được sử dụng làm ví dụ. – CKing

+0

@MarcusWidegren Vâng, đó là một cách hay để làm điều đó! Nhưng tôi thực sự muốn biết nếu có một cách để tạo ra loại BigDecimal tùy chỉnh .. Dù sao, tôi sẽ xem xét câu trả lời này đúng nếu không ai có thể giúp tôi với các loại tùy chỉnh, nhờ trả lời :) – yat0

+3

Nó có thể là có thể để phân lớp nó (nếu BigDecimal không được khai báo là final, mà nó có lẽ nên là vì nó được cho là không thay đổi), nhưng nó sẽ không giải quyết được vấn đề của bạn vì trạng thái của nó không thể thay đổi sau khi tạo. Nếu bạn muốn có một loại tùy chỉnh, tôi sẽ đi với một loại * có * một BigDecimal thay vì * là * một. Bằng cách đó bạn có thể tạo BigDecimal và thay đổi trạng thái của nó, trong hàm tạo của bạn. :) –

7

Bạn có thể lưu trữ một cá thể đơn lẻ của MathContext, ví dụ, và sử dụng chúng làm đối số cho hàm dựng lớn.

Thông thường, bạn có thể làm:

MathContext context = new MathContext(2, RoundingMode.HALF_UP); 
BigDecimal number = new BigDecimal(val, context); 

Vì vậy, nếu bạn có một MathContext như singleton, bạn có thể làm:

BigDecimal number = new BigDecimal(val, MathInstanceHolder.getMathContext()); 

đâu MathInstanceHolder chứa một trường hợp MathContext.

+1

Humbly Tôi thích phương pháp này thay vì một wrapper. Tôi đã đề xuất một cá thể đơn vì giá trị sẽ không bao giờ thay đổi trong phạm vi ứng dụng và sẽ được sử dụng cho tất cả các phiên bản BigDecimal. Bằng cách này bạn có thể sử dụng BigDecimal như mọi khi và quy mô sẽ rõ ràng cho bất kỳ sự phát triển nào khác đọc mã. Tôi chỉ phân chia trách nhiệm nhưng đó là chủ quan. Đề xuất luôn được chào đón. –

+0

Tệ của tôi. Tôi hiểu lầm đề nghị của bạn. Tôi sẽ xóa nhận xét của tôi. –

+0

wow, tôi thực sự thích cách tiếp cận này .. Và tôi đồng ý với bạn trong những gì bạn nói, điều duy nhất BigDecimals của tôi sẽ có đặc biệt là 2 chữ số thập phân, vì vậy nếu tôi tạo một singleton như bạn nói, tôi có thể sử dụng BigDecimals bình thường như thường lệ và vẫn có thể thiết lập tỷ lệ trong constructor .. Awesome, cảm ơn! @DaniloGomes – yat0

0

Chỉ cần được khác nhau và sử dụng Java 8 - bạn cũng có thể đi lambda vào vấn đề:

public static Function<String, BigDecimal> SCALED_BIG_DECIMAL = (val) -> new BigDecimal(val).setScale(2, RoundingMode.HALF_UP); 
... 

// and this is how you would use it 
SCALED_BIG_DECIMAL.apply("20.2343425") 
Các vấn đề liên quan