2011-10-12 36 views
5

Tôi có mã đọc một tệp XML. Một số thuộc tính của các phần tử mà tôi cần xử lý là tùy chọn. Tôi đang cố gắng sử dụng Option [T] để quản lý chúng. Tôi đã viết những điều sau đây để dắt các loại NodeSeq trả về bởi các nhà điều hành \ Node:Xử lý các thuộc tính xml tùy chọn trong Scala

class NodeSeqWrapper(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 
implicit def nodeSeqWrapper(nodeSeq: NodeSeq): NodeSeqWrapper = 
    new NodeSeqWrapper(nodeSeq) 

và sau đó gọi nó như thế này:

(node \ "@attr").textOption.getOrElse("Some default value") 

Nếu nút có "attr" thuộc tính, mã này làm cho nó có giá trị. Nếu không, giá trị "Một số giá trị mặc định" được trả về.

Làm cách nào để cải thiện điều này? Có cách nào để gấp định nghĩa lớp vào phương pháp ngầm không? Có cách nào tốt hơn để nhận các giá trị thuộc tính "tùy chọn" không? Tôi có đang sử dụng Option[T] "chính xác" không?

+0

Bạn có thể muốn gọi phương thức 'textOption', theo cùng kiểu với phương thức' '' '' 'và' headOption'. –

+0

Nghe hay đấy. Tôi sẽ thay đổi mã của tôi. Cũng cập nhật câu hỏi. – Ralph

Trả lời

4

Tôi sẽ nói rằng bạn đang làm điều đó một cách rất thành ngữ, vâng.

Bạn có thể "gấp các định nghĩa" như sau:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 

Nếu bạn luôn được áp dụng .getOrElse(...) vào kết quả, bạn cũng có thể muốn xác định một phiên bản thứ hai textOrElse(elze : String) : String:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 

    def textOrElse(elze : String) : String = textOption.getOrElse(elze) 
} 

Đó sẽ làm cho mọi việc ngắn gọn hơn một chút.

scala> (<b>Hello</b> : NodeSeq).textOrElse("No text found.") 
resN: String = Hello 
scala> (<br /> : NodeSeq).textOrElse("No text found.") 
resM: String = No text found. 
+0

Đó là những gì tôi đang tìm kiếm. Tôi đã thử sử dụng một lớp vô danh trong lần thử đầu tiên của tôi ('new {...}') và nó không hoạt động. Tôi cũng thích phương thức 'textOrElse'. Cảm ơn. – Ralph

+2

Hãy coi chừng rằng "xếp các định nghĩa" làm cho sự phản chiếu Java được sử dụng mỗi lần bạn gọi các phương thức bổ sung của mình. Khai báo lớp phụ không. –

+0

@ Jean-PhilippePellet Điểm tốt! Tôi sẽ nghi ngờ trình biên dịch JIT JVM là khá tốt tại xử lý các cuộc gọi phản chiếu, nơi tên của phương pháp được đưa ra như là một chuỗi tĩnh, mặc dù. – Philippe

2

Câu trả lời có thể được cải thiện kể từ khi Scala 2.10 có giới thiệu các lớp ẩn.

http://docs.scala-lang.org/overviews/core/implicit-classes.html

Các ví dụ op đã có thể được viết lại bằng một lớp tiềm ẩn như vậy:

object SomeExtensions { 

    implicit class ExtendedNodeSeq(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
     val text = nodeSeq.text 
     if (text == null || text.length == 0) None else Some(text) 
    } 
    } 

} 

Lưu ý rằng ví dụ sau một vài hạn chế đối với trường hợp các lớp:

  1. Chúng phải được xác định bên trong một đặc tính/lớp/đối tượng khác.
  2. Chúng chỉ có thể lấy một đối số không ngụ ý trong hàm tạo của chúng.
Các vấn đề liên quan