2012-04-25 31 views
8

Tôi không thích Scala isInstanceOf và asInstanceOf phương pháp - họ là dài và asInstanceOf có thể ném ngoại lệ vì vậy chúng tôi cần phải sử dụng nó trong cặp vợ chồng. Cách tốt hơn là sử dụng mẫu phù hợp: Scala: How do I cast a variable? nhưng đối với các hoạt động thực sự đơn giản, nó có thể tương đối dài quá. Trong C# chúng ta có các toán tử 'is' và 'as' vì vậy tôi muốn triển khai thực hiện định nghĩa ngầm với điều này trong Scala. nhìn mã của tôi như thế này:Scala ngắn và loại nhà điều hành an toàn đúc

scala> class TypeCast(x:Any){ 
    | def is[T](t:Class[T]) = t.isInstance(x) 
    | def as[T](t:Class[T]):Option[T] = if(t.isInstance(x)) Option(t.cast(x)) else None 
    | } 
defined class TypeCast 

scala> implicit def TypeCastID(x:Any)=new TypeCast(x) 
TypeCastID: (x: Any)TypeCast 

scala> 123 as classOf[String] 
res14: Option[String] = None 

scala> "asd" as classOf[String] 
res15: Option[String] = Some(asd) 

Nó có một lợi thế - thực hiện mô hình null-đối tượng nhưng cũng có nhược điểm:

  • cần phải sử dụng classOf [T] hành - nó quá dài

  • overhead được kết nối với def ngầm định cho thao tác đơn giản như vậy

vì vậy lại là không có lý do thực tế để sử dụng nó. Tôi muốn biết có cách nào để thực hiện điều này mà không cần phải sử dụng classOf [T]?

+2

Theo tôi, nó là tốt 'isInstanceOf' và' asInstanceOf' có tên tương đối dài và bất tiện. Thông thường, bạn sẽ muốn tránh việc kiểm tra và đúc kiểu động và sử dụng phương pháp tiếp cận kiểu OO tốt hơn thay thế (đa hình) hoặc khớp mẫu (kiểu hàm). Các tên bất tiện khuyến khích bạn không sử dụng chúng quá nhiều. Trong tiêu đề của bạn, bạn đang yêu cầu "nhà điều hành dàn diễn viên an toàn". Việc đúc không bao giờ là loại an toàn, theo định nghĩa. – Jesper

+0

Tôi cho rằng sẽ có nhận xét tương tự. Nói chung tôi đồng ý với bạn rằng thiết kế tốt và phù hợp với mô hình là tốt hơn nhiều. Nhưng đôi khi IMHO 'như' ký hiệu ngắn hơn và rõ ràng hơn nhiều. Ví dụ, chúng ta có thể sử dụng thư viện của bên thứ ba nơi thiết kế không tốt như chúng ta cần. Nó cũng trả về Option [T] thay vì T để an toàn hơn. Và cuối cùng: trả lời cho câu hỏi này hầu hết tất cả cho tôi thêm kiến ​​thức về Scala :) – theres

Trả lời

10

Vâng, bạn có thể rút ngắn nó xuống bên trong def bạn đã thực hiện trong lớp TypeCast. Vì vậy, thay vì cho ăn nó một tham số bạn chỉ có thể dựa vào loại. Điều này sẽ rút ngắn nó xuống rất nhiều. Như một ví dụ này có thể giống như thế:

class TypeCast(x : Any) { 
    def is[T : Manifest] = manifest.erasure.isInstance(x) 
    def as[T : Manifest] : Option[T] = if (manifest.erasure.isInstance(x)) Some(x.asInstanceOf[T]) else None 
} 

cuộc gọi trong tương lai có thể trông giống như:

scala> 123.as[String] 
res0: Option[String] = Some(123) 
scala> class A; class B extends A 
defined class A 
defined class B 
scala> new B 
res1: B 
scala> res1.is[Int] 
res2: Boolean = false 
scala> res1.as[Int] 
res3: Option[Int] = None 

Cập nhật: Tôi thêm Manifests để tránh các lỗi kiểu kiểm tra

+0

Tôi thử giải pháp tương tự, nhưng điều này không may không hoạt động chính xác: lớp A; lớp B mở rộng A; val b = new B; b.as [Int] cho mi Một số (instance-of-B) thay vì None và cũng b.is [Int] trả về true – theres

+2

Dường như bạn có thể sử dụng tệp kê khai để xóa mọi thứ .. Tôi sẽ cập nhật mã . –

+0

Cảm ơn! Tôi chưa bao giờ nghe nói về Manifests trước đây. – theres