在嵌套类

时间:2015-10-25 20:49:25

标签: java scala

以下是代码:

import scala.collection.mutable

/**
 * Created by IDEA on 25/10/15.
 */
class HttpRequest(builder: Builder) {
  val headers: Map[String, String]
  var body: String
  var path: String

  class Builder {innerBuilder =>
    private val headers = new mutable.HashMap[String, String]()
    private var body: String = _
    private var path: String = _

    def addHeader(name: String, value: String): Unit = {
      headers.put(name, value)
      innerBuilder
    }

    def body(b: String): Builder = {
      body = b
      innerBuilder
    }

    def path(p: String) = {
      path = p
      innerBuilder
    }

    def build: HttpRequest = {
      new HttpRequest(innerBuilder)
    }
  }
}

我有两个错误:

Error:(27, 7) overloaded method path needs result type
      path = p
      ^
Error:(32, 23) type mismatch;
 found   : HttpRequest.this.Builder
 required: Builder
      new HttpRequest(innerBuilder)
                      ^

我做错了什么?

BTW,我试图将这个java文件翻译成scala:

/***
 * Excerpted from "Functional Programming Patterns",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/mbfpp for more book information.
***/
package com.mblinn.oo.tinyweb;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {
    private Map<String, String> headers;
    private String body;
    private String path;

    public Map<String, String> getHeaders() {
        return headers;
    }

    public String getBody() {
        return body;
    }

    public String getPath() {
        return path;
    }

    private HttpRequest(Builder builder) {
        this.headers = Collections.unmodifiableMap(builder.headers);
        this.body = builder.body;
        this.path = builder.path;
    }

    public static class Builder {
        private Map<String, String> headers;
        private String body;
        private String path;

        private Builder() {
            headers = new HashMap<String, String>();
        }

        public Builder addHeader(String name, String value) {
            headers.put(name, value);
            return this;
        }

        public Builder body(String body) {
            this.body = body;
            return this;
        }

        public Builder path(String path) {
            this.path = path;
            return this;
        }

        public HttpRequest build() {
            return new HttpRequest(this);
        }

        public static Builder newBuilder() {
            return new Builder();
        }

        public static Builder builderFrom(HttpRequest request) {
            Builder builder = new Builder();
            builder.path(request.getPath());
            builder.body(request.getBody());

            Map<String, String> headers = request.getHeaders();
            for (String headerName : headers.keySet())
                builder.addHeader(headerName, 
                        headers.get(headerName));

            return builder;
        }
    }
}

更新1

import scala.collection.mutable.Map

/**
 * Created by IDEA on 25/10/15.
 */
class HttpRequest(builder: Builder) {
  val headers: Map[String, String] = Map.empty
  var body: String = _
  var path: String = _

  import scala.collection.mutable

  class Builder {
    private val headers = new mutable.HashMap[String, String]()
    private var body: String = _
    private var path: String = _

    def addHeader(name: String, value: String): this.type = {
      headers.put(name, value)
      this
    }

    def body(b: String): this.type = {
      body = b
      this
    }

    def path(p: String): this.type = {
      path = p
      this
    }

//    def build: HttpRequest = {
//      new HttpRequest(this)
//    }
  }
}

还有两个问题:

  1. 似乎不允许在外部类的构造中引用内部类(intellij无法解析它)

  2. new HttpRequest(this)报告类型不匹配。

1 个答案:

答案 0 :(得分:4)

你提到的其余两点的问题是BuilderHttpRequest的内部类(事实上,正如所写的那样,它是{的每个特定实例的单独定义的内部类。 {1}}!),因此需要以HttpRequest类型的方式解决。但要正确地完成这项工作,您需要将Builder的定义移动到HttpRequest.Builder的伴随对象中。类似的东西:

HttpRequest

这里有几点说明:

  • 我使HttpRequest成为一个案例类,因为它更适合Scala数据类
  • case class HttpRequest(headers: Map[String, String], body: String, path: String) object HttpRequest { def apply(builder: HttpRequest.Builder): HttpRequest = HttpRequest(Map(builder.headers.toSeq: _*), builder.body, builder.path) class Builder { private[HttpRequest] val headers = new mutable.HashMap[String, String]() private[HttpRequest] var body: String = _ private[HttpRequest] var path: String = _ def addHeader(name: String, value: String): Builder = { headers.put(name, value) this } def body(b: String): Builder = { body = b this } def path(p: String): Builder = { this.path = p this } def build: HttpRequest = { HttpRequest(this) } } def builderFrom(request: HttpRequest): Builder = { val builder = new Builder().path(request.path).body(request.body) request.headers.foldLeft(builder){ (b,h) => b.addHeader(h._1, h._2) } } } 类现在位于伴随对象中(可以被认为是Java中标记为“静态”的所有内容的持有者,尽管它不仅仅是这样,特别是对于案例类)。
  • 同伴对象也是放置Builder方法的地方,buildFrom方法通过链接方法调用和请求标题的折叠构建Builder。因为折叠产生Builder作为结果,所以这将是buildFrom方法的返回值。
  • private[HttpRequest]字段上的Builder访问修饰符可确保这些字段仅在HttpRequest类中可见,其中包含内部Builder类(需要它们以便它们可以可以使用apply方法访问。
  • 我只检查过上面的代码是在控制台中编译的 - 我实际上并没有按照它的步骤编写代码。