2009-05-04 40 views
16

Tôi cố gắng để viết một số mã Scala mà cần phải làm điều gì đó như:Tóm tắt các loại/Loại Các tham số trong Scala

class Test[Type] { 
    def main { 
     SomeFunc classOf[Type] 
     val testVal: Type = new Type() 
    } 
} 

và nó thất bại. Tôi rõ ràng không hiểu gì về các thông số chung của Scala. Rõ ràng, sự hiểu lầm là trong C++, các mẫu về cơ bản hoạt động như chuỗi thay thế, vì vậy Type mới() sẽ hoạt động miễn là lớp được truyền vào có một hàm tạo mặc định. Tuy nhiên, trong Scala, các loại là các loại đối tượng khác nhau.

+0

Câu hỏi là gì? – stepancheg

+0

Làm cách nào để thực hiện công việc này? – bsdfish

Trả lời

28

Khi bạn chỉ ra, C++ có mẫu. Tóm lại, C++ nói "có một thử nghiệm cho tất cả các loại T sao cho biên dịch thử nghiệm." Điều đó làm cho nó dễ dàng để ngầm thêm ràng buộc vào T, nhưng ở phía bên dưới chúng ngầm định và có thể khó cho người dùng của lớp bạn hiểu mà không cần đọc mã.

Đa hình tham số của Scala (còn gọi là generics) hoạt động nhiều hơn như ML, Haskell, Java và C#. Trong Scala, khi bạn viết "class Test [T]" bạn đang nói "cho tất cả T tồn tại một loại Test [T]" mà không bị ràng buộc. Đó là đơn giản hơn để lý do về chính thức, nhưng nó có nghĩa là bạn phải rõ ràng về những hạn chế. Ví dụ, trong Scala bạn có thể nói "class Test [T <: Foo]" để nói rằng T phải là một subtype của Foo.

C# có cách thêm ràng buộc vào T liên quan đến nhà thầu, nhưng không may Scala thì không.

Có một số cách để giải quyết vấn đề của bạn trong Scala. Một là an toàn nhưng an toàn hơn. Cái kia không an toàn.

Cách typesafe trông giống như

class Test[T](implicit val factory :() => T) { 
    val testVal = factory 
} 

Sau đó, bạn có thể có một cơ thể của nhà máy với nhiều loại hữu ích trong hệ thống

object Factories { 
    implicit def listfact[X]() = List[X]() 
    implicit def setfact[X]() = Set[X]() 
    // etc 
} 

import Factories._ 
val t = new Test[Set[String]] 

bạn Nếu người sử dụng thư viện của bạn cần các nhà máy riêng của họ sau đó họ có thể thêm tương đương với đối tượng Nhà máy của họ. Một lợi thế của giải pháp này là bất cứ điều gì với một nhà máy có thể được sử dụng, có hoặc không có một constructor no-arg.

Cách không-để-typesafe sử dụng phản xạ và một tính năng trong Scala gọi là biểu hiện đó là một cách để có được xung quanh một hạn chế Java về loại chô bôi

class Test[T](implicit m : Manifest[T]) { 
    val testVal = m.erasure.newInstance().asInstanceOf[T] 
} 

Với phiên bản này, bạn vẫn viết

class Foo 
val t = new Test[Foo] 

Tuy nhiên, nếu không có hàm tạo no-arg, bạn có ngoại lệ thời gian chạy thay vì lỗi loại tĩnh

scala> new Test[Set[String]] 
java.lang.InstantiationException: scala.collection.immutable.Set 
at java.lang.Class.newInstance0(Class.java:340) 
+0

Một trong hai cách tiếp cận này có làm việc với các hàm tạo dựa trên tham số cho T không? –

Các vấn đề liên quan