2014-11-11 17 views
5

Tôi có một lớp Java mà tôi muốn phân lớp. Lớp con chỉ thêm các phương thức tiện lợi - tất cả có thể được thực hiện bằng cách sử dụng các phương thức bên ngoài, bởi vì tôi chỉ xem xét các trường công khai và tôi không sửa đổi bất kỳ thứ gì.Scala - Mở rộng một loại tham chiếu mà không cần phân lớp nó

Nếu lớp cơ sở là loại giá trị, tôi muốn sử dụng trình bao bọc giá trị - extends AnyVal. Nhưng lớp cơ sở là một kiểu tham chiếu Java. Có cách nào tốt hơn để phân lớp nó ngoài việc mở rộng nó?

+1

Sự khác biệt là gì? Không phải tất cả các lớp trong các kiểu tham chiếu Scala Java phải không? Tất cả chúng đều mở rộng java.lang.Object. (Đây là một câu hỏi nghiêm túc, btw. Tôi thực sự không hiểu những gì bạn đang cố gắng làm.) – markspace

+2

Nếu bạn không muốn mở rộng nó, bạn có thể sử dụng mẫu * Pimp My Library *. –

+1

Lưu ý rằng bạn có thể sử dụng các lớp giá trị để bao bọc các loại không có giá trị — xem [câu trả lời của tôi bên dưới] (http://stackoverflow.com/a/26869791/334519) để có trình diễn. –

Trả lời

10

Để giải quyết đoạn thứ hai của bạn đặc biệt, loại bạn quấn bằng một lớp giá trị thể là một loại tài liệu tham khảo và bạn vẫn tránh được thêm phân bổ đối tượng thường được tham gia vào gói. Ví dụ, nếu bạn đã có những lớp ẩn:

implicit class MyInt(val underlying: Int) extends AnyVal { 
    def inc: Int = underlying + 1 
} 

implicit class MyString(val underlying: String) extends AnyVal { 
    def firstChar: Char = underlying.charAt(0) 
} 

implicit class MyNonValueClassString(val underlying: String) { 
    def firstCharNonValueClass: Char = underlying.charAt(0) 
} 

Và mã này có sử dụng chúng:

println(42.inc) 
println("hello".firstChar) 
println("hello".firstCharNonValueClass) 

Bạn có thể biên dịch với -Xprint:flatten để xem phiên bản khử đường (định dạng lại ở đây cho rõ ràng):

scala.this.Predef.println(
    scala.Int.box(Demo$MyInt.this.inc$extension(Demo.this.MyInt(42))) 
); 

scala.this.Predef.println(
    scala.Char.box(
    Demo$MyString.this.firstChar$extension(Demo.this.MyString("hello")) 
) 
); 

scala.this.Predef.println(
    scala.Char.box(
    Demo.this.MyNonValueClassString("hello").firstCharNonValueClass() 
) 
); 

Như bạn có thể thấy, các cuộc gọi firstChar không liên quan đến một đối tượng mới.

2

Thành phần ưu tiên hơn thừa kế.

Vì vậy, trong trường hợp của bạn, cách tốt nhất có thể là tạo một lớp có lớp Java làm thuộc tính. Sau đó, bạn chỉ có thể ủy thác các phương pháp của các đối tượng này và thêm của riêng bạn:

class MyClass(jo: JavaObject) { 
    def delegateMethod() = jo.method() 
    def newMethod() = // ... 
} 
Các vấn đề liên quan