2010-07-18 42 views
6

Tôi đang cố gắng để tạo ra một thể hiện của một đặc điểm sử dụng phương pháp nàyLàm cách nào để tạo một cá thể của một đặc điểm trong một phương thức chung trong scala?

val inst = new Object with MyTrait 

này hoạt động tốt, nhưng tôi muốn di chuyển sáng tạo này vào một chức năng máy phát điện, tức là.

object Creator { 
    def create[T] : T = new Object with T 
} 

Tôi rõ ràng là sẽ cần manifest để bằng cách nào đó sửa chữa những vấn đề loại tẩy xoá, nhưng trước khi tôi nhận được điều này, tôi chạy vào 2 câu hỏi:

  1. Ngay cả với một biểu hiện tiềm ẩn , Scala vẫn yêu cầu T là một đặc điểm. Làm thế nào để thêm một hạn chế để tạo [T] sao cho T là một đặc tính?

  2. Nếu tôi chọn sử dụng phương thức Class.newInstance để tạo cá thể động thay vì sử dụng "mới", làm cách nào tôi chỉ định "có" trong "đối tượng mới có T"? Có thể tự động tạo các loại mixin cụ thể mới trong thời gian chạy không?

Trả lời

8

Bạn không thể thực hiện việc này (ngay cả với Tệp kê khai). Mã new Object with T liên quan đến việc tạo một lớp ẩn danh mới đại diện cho sự kết hợp của Object with T. Để truyền điều này đến hàm create của bạn, bạn sẽ phải tạo ra lớp mới này (với bytecode mới) khi chạy và Scala không có cơ sở để tạo một lớp mới khi chạy.

Một chiến lược có thể là cố gắng chuyển chức năng đặc biệt của phương thức nhà máy vào hàm tạo của lớp thay thế, sau đó sử dụng hàm tạo trực tiếp.

Một chiến lược khác có thể là tạo các hàm chuyển đổi (ẩn hoặc khác) thành các đặc điểm bạn quan tâm đến việc sử dụng với lớp này.

+0

Điều này có vẻ là một giới hạn thú vị của ngôn ngữ, nhưng tôi không thấy lý do tại sao nó không thể được sửa với hỗ trợ mixin "Động" mới trong Scala. Mã tra cứu đã có sẵn dưới dạng các phương thức tĩnh, vì vậy việc tra cứu tuyến tính có thể được tính toán trong thời gian chạy thay vì được đưa vào lớp bytecode. Sau đó, bạn chỉ cần thêm kiểm tra kiểu thời gian chạy để "asInstanceOf" hoạt động. – ACyclic

14

Tôi không chắc động lực là gì cho câu hỏi của bạn, nhưng bạn có thể xem xét chuyển nhà máy cho T làm thông số ẩn. Điều này được gọi là sử dụng các lớp loại loại hoặc đa hình ad-hoc.

object Test extends Application { 
    trait Factory[T] { 
    def apply: T 
    } 
    object Factory { 
    /** 
    * Construct a factory for type `T` that creates a new instance by 
    * invoking the by-name parameter `t` 
    */ 
    def apply[T](t: => T): Factory[T] = new Factory[T] { 
     def apply = t 
    } 
    } 

    // define a few traits... 
    trait T1 
    trait T2 

    // ...and corresponding instances of the `Factory` type class. 
    implicit val T1Factory: Factory[T1] = Factory(new T1{}) 
    implicit val T2Factory: Factory[T2] = Factory(new T2{}) 

    // Use a context bound to restrict type parameter T 
    // by requiring an implicit parameter of type `Factory[T]` 
    def create[T: Factory]: T = implicitly[Factory[T]].apply 

    create[T1] 
    create[T2] 

} 

Ở đầu kia của quang phổ, bạn có thể gọi trình biên dịch tại thời gian chạy, được nêu chi tiết trong this answer cho câu hỏi "Dynamic mixin trong Scala - là nó có thể".

+0

Cảm ơn, tôi có thể phải sử dụng phương pháp này. Trường hợp sử dụng của tôi là Proxy Java. Tôi muốn viết một thư viện có thể truy cập từ xa. Do đó, tôi cần xác định các giao diện cho tất cả các lớp học của mình, đó là một nỗi đau khi tôi muốn phơi bày mọi thứ. Một giải pháp là viết tất cả mọi thứ như một đặc điểm, sau đó tôi nhận được định nghĩa giao diện miễn phí. Mục đích của chức năng tạo ra là để tạo ra một đặc điểm ở phía "cụ thể" của kết nối proxy. – ACyclic

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