2

play 2.1 アプリケーションには、次のコードがあります (末尾のスラッシュを取り除く単なるリクエスト ラッパーです)。

class NormalizedRequest(request: RequestHeader) extends RequestHeader {

  val headers = request.headers
  val id = request.id
  val method = request.method
  val queryString = request.queryString
  val remoteAddress = request.remoteAddress
  val tags = request.tags
  val version = request.version

  // strip first part of path and uri if it matches http.path config
  val path = if (request.path == "/") "/" else request.path.stripSuffix("/")
  val uri = path + {
    if(request.rawQueryString == "") ""
    else "?" + request.rawQueryString
  }
}

object NormalizedRequest {
  def apply(request: RequestHeader) = new NormalizedRequest(request)
}

この種のコードはかなり一般的です。オブジェクトを別のオブジェクトにラップするだけです

私はそれを達成するためのより簡単な方法があるかどうか疑問に思っていました.理想的には次のようなものです(ケースクラスに触発された擬似コード):

object NormalizedRequest {
  def apply(request: RequestHeader) = {
    val path = if (request.path == "/") "/" else request.path.stripSuffix("/")
    val uri = path + {
      if(request.rawQueryString == "") ""
      else "?" + request.rawQueryString
    }
    request.copy(path = path, uri = uri)
  }
}
4

1 に答える 1

5

私の理解が正しければ、あなたは scala でデコレータ パターンのより簡潔なバージョンを求めています。内部クラスのインスタンスを受け取ることを期待する関数に渡すことができるようにするには、「ラッパー」を内部クラスと同じ型にする必要があります (それまたは共通の基本/特性を拡張することにより)。または共通のベース/特性の)。

疑似コードに記述したものは、実際にはほぼ合法的なスカラです。 applyinの定義を変更して、 NormalizedRequestRequestHeader を拡張する匿名クラスを返すだけです。

つまり、代わりに

class NormalizedRequest(request: RequestHeader) extends RequestHeader {
    //.... "decorated" logic here
}
object NormalizedRequest {
  def apply(request: RequestHeader) = new NormalizedRequest(request)
}

あなたが持っているだろう

object NormalizedRequest {
  def apply(request: RequestHeader) = new RequestHeader {
    // ...
    // instead of having a separate NormalizedRequest class
    // define its behaviour here in anonymous form    
    }
}

簡単な例:

// our inner class and companion object 
// (a simplified version of your RequestHeader)
class Inner() {def test="hello"}; object Inner {
    def apply() = new Inner()
} 

// our wrapper
object Outer {
    def apply(inner: Inner) = new Inner {
        override def test=inner.test + "!"
    }   
}

ただし、いくつかのキーストロークを節約できますが、読みやすさが失われると思います.

于 2012-11-20T13:57:07.667 に答える