2014-09-04 13 views
6

Tôi thường gặp phải tình huống mà tôi có phương pháp nhà máy đối với một số đặc điểm và tên đối số xung đột với các thành viên của đặc điểm khiến chúng bị ẩn:Scala - cách tạo lớp ẩn danh và tránh ẩn tên đối số

trait MyTrait { 
    val a: Int 
    val b: String 
} 

object MyTrait { 
    def apply(a: Int, b: String): MyTrait = new MyTrait { 
     val a = a // Recursive infinite loop. 
     val b = b 
    } 
} 

Vì vậy, thường tôi phải làm một cái gì đó xấu xí như:

def apply(aA: Int, bB: String): MyTrait = new MyTrait { 
     val a = aA 
     val b = bB 
    } 

hoặc làm bản sao cục bộ của đối số:

def apply(a: Int, b: String): MyTrait = { 
     val localA = a 
     val localB = b 

     new MyTrait {   
      val a = localA 
      val b = localB 
    } 

Tôi muốn các tham số cho phương thức apply giống với các thành viên của đặc điểm của tôi, để mã khách hàng đọc độc đáo khi tôi sử dụng các tham số được đặt tên: ví dụ: MyTrait(a=3,b="123").

Có cơ chế neater cho phép tôi nắm bắt phạm vi bên ngoài nơi các tham số đối số được xác định hay không, nhưng lớp ẩn danh chưa? Ví dụ:

def apply(a: Int, b: String): MyTrait = { outer => 
     new MyTrait { 
      val a = outer.a 
      val b = outer.b 
     } 
    } 

Cảm ơn!

+1

Duplicate http://stackoverflow.com/q/ 12229005/1296806 –

Trả lời

2

Nếu chúng ta cần tạo một cá thể, tại sao không ủy quyền nó cho hàm tạo. Vì vậy, tôi có thể nghĩ đến hack này:

trait MyTrait { 
    def a: Int 
    def b: String 
} 

object MyTrait { 
    private class MkMyTrait(val a: Int, val b: String) extends MyTrait 
    def apply(a: Int, b: String): MyTrait = new MkMyTrait(a, b) 
} 
+0

Cảm ơn câu trả lời. Điều đó chỉ thực sự hiệu quả đối với tôi nếu việc thực hiện đặc điểm của tôi là thông qua dữ liệu ngay trong ví dụ của bạn. Thường có lần khi tôi tạo một số chuyên gia triển khai và tôi cần sử dụng từ khóa 'mới'. Tôi chỉ giữ ví dụ đơn giản để làm nổi bật vấn đề. – rmin

2

câu trả lời của tôi để gạt người, mà không tiết kiệm hơn nhiều:

trait T { val t: Int } 
object T { 
    def apply(t: Int): T = new { 
    private[this] val x = t 
    } with T { 
    val t = x 
    } 
} 

Ngoài ra, -optimise không thoát khỏi hiện trường.

Dưới đây là một ý tưởng khác: bí danh tên param.

Ngay sau đó, chúng ta sẽ có thể lọc các cảnh báo một cách chọn lọc, vì vậy nó sẽ có thể bỏ qua các cảnh báo được tạo ra khi không dùng nữa được kích hoạt:

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

trait T { val t: Int } 
object T { 
    def apply(@deprecatedName('t) t0: Int): T = new T { val t = t0 } 
} 

// Exiting paste mode, now interpreting. 

defined trait T 
defined object T 

scala> T(t = 42) 
warning: there was one deprecation warning; re-run with -deprecation for details 
res1: T = [email protected] 
Các vấn đề liên quan