2013-04-19 15 views
5

Tôi không thực sự hiểu được điều này. Tôi có một lớp trừu tượng Hộp với một số lớp con cho các loại khác nhau. Ví dụLàm thế nào để sử dụng vắt trong đa hình unapply?

abstract class Box 
class StringBox(val sValue : String) extends Box 

Phương pháp áp dụng trong các đối tượng đồng cho Box rất đơn giản:

object Box{ 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 
} 

vì vậy tôi có thể viết

val sb = Box("StringBox) 

Được rồi, viết unapply làm cho một số rắc rối. Ý tưởng đầu tiên của tôi là sử dụng mô hình kết hợp vào loại, như thế này này:

def unapply(b: Box) = b match { 
    case sb: StringBox => Some(sb.sValue) 
    case bb: BooleanBox => Some(bb.bValue) 
    case db: DoubleBox => Some(db.dValue) 
    case _ => None 

}

Mà chỉ đơn giản là không làm việc vì loại tẩy xóa.

Lần thử thứ hai là một hộp chung [T] với loại T và một thành phần kiểu trừu tượng được xác định lại trong mỗi lớp con. Ví dụ:

abstract class Box[T] {def value : T} 
class StringBox(val sValue : String) extends Box[String] { 
    override def value : String = sValue 
} 

Do đó, tôi có thể tái viết unapply tôi như:

def unapply[T](b: Box[T]) = b match { 
    case sb: Box[String] => Some(sb.value) 
    case bb: Box[Boolean] => Some(bb.value) 
    case db: Box[Double] => Some(db.value) 
    case _ => None 

Thật không may, điều này không làm việc, hoặc. Vì vậy, tôi đoán tham chiếu kiểu rõ ràng trong Hộp [Chuỗi] cũng bị xóa vì vậy tôi cần phải sử dụng tệp kê khai loại thay thế. Có thể một cái gì đó như:

def unapply[T](b: Box[_])(implicit target: Manifest[T]): Option[T] = { 

    if(b.value == target) Some(b.value.asInstanceOf[T]) 
    else None 
} 

Mã này biên dịch (2.10) nhưng vẫn không chuyển đổi ẩn mong muốn. Tại sao?

Câu hỏi đơn giản, có cách nào để thực hiện trích xuất giá trị mà không sử dụng phản chiếu hoặc tệp kê khai không?

Điều gì thực sự boggles tôi là câu hỏi nếu có một cách (r) đơn giản để kết hợp đa hình và khớp mẫu? Nếu không, có cách nào khác trong Scala để thực hiện một hiệu ứng tương tự?

Bất kỳ ý tưởng hoặc đề xuất nào?

Cảm ơn bạn rất nhiều.

Trả lời

5

Prolly bạn có thể thử này .. :)

abstract class Box[T](val v: T) 

    object Box { 
    def apply(s: String) = new StringBox(s) 
    def apply(b: Boolean) = new BooleanBox(b) 
    def apply(d: Double) = new DoubleBox(d) 

    } 

    class StringBox(sValue: String) extends Box(sValue) 
    object StringBox { 
    def unapply(b: StringBox) = Some(b.v) 
    } 

    class BooleanBox(sValue: Boolean) extends Box(sValue) 
    object BooleanBox { 
    def unapply(b: BooleanBox) = Some(b.v) 
    } 

    class DoubleBox(sValue: Double) extends Box(sValue) 
    object DoubleBox { 
    def unapply(b: DoubleBox) = Some(b.v) 
    } 

Bạn có thể sử dụng nó như -

def useCase[T](box: Box[T]) = box match { 
    case StringBox("StringBoxxx") => "I found the StringBox!" 
    case StringBox(s) => "Some other StringBox" 
    case BooleanBox(b) => { 
      if (b) "Omg! its true BooleanBox !" 
      else "its false BooleanBox :(" 
      } 
    case DoubleBox(x) => { 
       if (x > 3.14) "DoubleBox greater than pie !" 
       else if (x == 3.14) "DoubleBox with a pie !" 
       else "DoubleBox less than a pie !" 
    } 
    case _ => "What is it yaa ?" 
    }            

    useCase(Box("StringBoxxx")) //> res0: String = I found the StringBox! 
    useCase(Box("Whatever !")) //> res1: String = Some other StringBox 
    useCase(Box(true))   //> res2: String = Omg! its true BooleanBox ! 
    useCase(Box(false))   //> res3: String = its false BooleanBox :(
    useCase(Box(4))    //> res4: String = DoubleBox greater than pie ! 
    useCase(Box(3.14))   //> res5: String = DoubleBox with a pie ! 
    useCase(Box(2))    //> res6: String = DoubleBox less than a pie ! 
+0

Vâng, đó là nó. Cảm ơn bạn. –

+0

Chào mừng bạn .. :) – Shrey

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