Tôi muốn loại bỏ một thời gian chạy diễn viên chung (asInstanceOf[A]
) mà không có chuyển đổi tiềm ẩn.Trả về bản sao của trường hợp lớp từ chức năng chung mà không có thời gian chạy diễn viên
Điều này xảy ra khi tôi có mô hình dữ liệu khá sạch sẽ bao gồm các lớp chữ thường có đặc điểm chung và muốn triển khai một thuật toán chung trên đó. Ví dụ, thuật toán kết quả sẽ lấy một lớp kiểu A
là một lớp con của trait T
và được cho là trả về một bản sao của lớp bê tông A
với một số trường được cập nhật.
Điều này rất dễ thực hiện khi tôi chỉ cần thêm một phép tính trừu tượng copy
vào đặc điểm cơ sở và thực hiện điều đó trong tất cả các lớp con. Tuy nhiên điều này có khả năng gây ô nhiễm cho mô hình với các phương thức chỉ được yêu cầu bởi các thuật toán nhất định và đôi khi không thể thực hiện được vì mô hình có thể nằm ngoài tầm kiểm soát của tôi.
Dưới đây là một ví dụ đơn giản để minh họa sự cố và giải pháp bằng cách sử dụng thời gian chạy phôi.
Vui lòng không bị treo lên các chi tiết.
Giả sử có một đặc điểm và một số lớp trường hợp tôi không thể thay đổi:
trait Share {
def absolute: Int
}
case class CommonShare(
issuedOn: String,
absolute: Int,
percentOfCompany: Float)
extends Share
case class PreferredShare(
issuedOn: String,
absolute: Int,
percentOfCompany: Float)
extends Share
Và đây là một phương pháp đơn giản để tính toán lại dòng percentOfCompany
khi tổng số cổ phần đã thay đổi và cập nhật các trường trong lớp trường hợp
def recalculateShare[A <: Share](share: A, currentTotalShares: Int): A = {
def copyOfShareWith(newPercentage: Float) = {
share match {
case common: CommonShare => common.copy(percentOfCompany = newPercentage)
case preferred: PreferredShare => preferred.copy(percentOfCompany = newPercentage)
}
}
copyOfShareWith(share.absolute/currentTotalShares.toFloat).asInstanceOf[A]
}
Một số ví dụ lời gọi trên REPL:
scala> recalculateShare(CommonShare("2014-01-01", 100, 0.5f), 400)
res0: CommonShare = CommonShare(2014-01-01,100,0.25)
scala> recalculateShare(PreferredShare("2014-01-01", 50, 0.5f), 400)
res1: PreferredShare = PreferredShare(2014-01-01,50,0.125)
Vì vậy, nó hoạt động và theo như tôi hiểu cuộc gọi .asInstanceOf[A]
sẽ không bao giờ thất bại nhưng là cần thiết để làm cho biên dịch mã. Có cách nào để tránh các diễn viên thời gian chạy một cách an toàn loại mà không có chuyển đổi tiềm ẩn?
Tôi không nghĩ vậy. Bạn sẽ cần một bằng chứng tiềm ẩn của typetag. Nếu không, bạn sẽ gặp phải vấn đề về xóa. –