2012-10-07 27 views
17

Tôi đang cố gắng để xác định một lớp học với một số phương pháp dùng một tham số ngầm:Làm thế nào để mang lại giá trị mặc định cho các thông số ngầm ở cấp lớp

object Greetings { 
    def say(name: String)(implicit greetings: String): String = greetings + " " +name 
} 

tôi sử dụng lớp này từ một lớp khác

implicit val greetings = "hello"    //> greetings : java.lang.String = hello 
Greetings.say("loic")       //> res0: String = hello loic 
Greetings.say("loic")("hi")      //> res1: String = hi loic 

Vấn đề của tôi là nó hoạt động chỉ khi tôi xác định val tiềm ẩn bên ngoài đối tượng Greetings của tôi. Tôi muốn có thể cung cấp các phương thức với các tham số ngầm, với một giá trị mặc định bên trong lớp của tôi, để làm cho việc sử dụng API của tôi dễ dàng hơn (như API thu thập Scala).

Vì vậy, tôi muốn làm điều này, nhưng nó không làm việc (không tìm thấy giá trị tiềm ẩn):

object Greetings { 
    implicit val greetings = "hello"  
    def say(name: String)(implicit greetings: String): String = greetings + " " +name 
} 

và sau đó

Greetings.say("loic")       
Greetings.say("loic")("hi") 

Tôi biết tôi có thể xác định một giá trị mặc định với (implicit greetings: String = "hello") nhưng Tôi muốn làm điều đó ở cấp lớp, để tránh lặp lại nếu có nhiều phương pháp.

Tôi đoán tôi thiếu điều gì đó vì tôi thấy rằng CanBuildFrom được định nghĩa bên trong lớp List, chẳng hạn.

Trả lời

6

Tôi đã tìm thấy một workaround:

class Greetings(implicit val greetings: String = "hello") { 
    def say(name: String): String = greetings + " " + name 
} 

Như thế này tôi có thể có một giá trị mặc định và ghi đè lên nó nếu tôi muốn:

new Greetings().say("loic")      //> res0: String = hello loic 

implicit val greetings = "hi"     //> greetings : java.lang.String = hi 
new Greetings().say("loic")      //> res1: String = hi loic 

new Greetings()("coucou").say("loic")   //> res2: String = coucou loic 

Lưu ý: new Greetings()("coucou") đang làm việc, không new Greetings("coucou"), bởi vì của một cú pháp kỳ lạ được giải thích here.

+0

Nó không phải là lạ, vì tiềm ẩn sẽ chỉ được chèn vào thứ hai để các thông số bình thường. Thông thường lớp học của bạn sẽ trông giống như 'class Greetings() (ngụ ý val ...)' – thatsIch

24

Bạn nên sử dụng loại chung như String trong ẩn. Lý do chính là tra cứu tiềm ẩn chỉ dựa trên loại, vì vậy nếu người khác định nghĩa giá trị tiềm ẩn khác của loại Chuỗi thì sao? Bạn có thể kết thúc với một cuộc xung đột. Vì vậy, bạn nên xác định loại hình cụ thể của riêng bạn cho mục đích của riêng bạn (một wrapper đơn giản xung quanh String).

Lý do khác là khi tìm kiếm các giá trị tiềm ẩn, trình biên dịch sẽ xem (trong số các vị trí khác) vào đối tượng đồng hành (nếu có) của loại giá trị ngầm định. Bạn có thể dễ dàng thấy nó hữu ích như thế nào, vì đối tượng đồng hành là nơi tự nhiên để đặt một giá trị ngầm định mặc định (như trong trường hợp của bạn). Nhưng nếu giá trị tiềm ẩn thuộc loại bạn không sở hữu (chẳng hạn như String), bạn không thể viết đối tượng đồng hành cho nó, trong khi với loại trình bao bọc của riêng bạn thì không có vấn đề gì.

OK, đủ nói dài giòng, đây là cách bạn có thể làm điều đó:

case class Greetings(value: String) { 
    override def toString = value 
} 
object Greetings { 
    // this implicit is just so that we don't have to manually wrap 
    // the string when explicitly passing a Greetings instance 
    implicit def stringToGreetings(value: String) = Greetings(value) 

    // default implicit Greetings value 
    implicit val greetings: Greetings ="hello" 

    def say(name: String)(implicit greetings: Greetings): String = greetings + " " +name 
} 
Greetings.say("loic")       
Greetings.say("loic")("hi") 
+0

Ok tôi nhận được nó, cảm ơn nhiều :) – Loic

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