使用空抽象类有什么好的替代方法?

时间:2015-08-13 11:42:56

标签: java abstract

假设我有以下内容:

public abstract class AbstractResponse {
  // this class is totally empty!
}

public class ResponseA extends AbstractResponse {
  // JSON POJO 
}

public class ResponseB extends AbstractResponse {
  // JSON POJO 
}

public abstract class AbstractClient {
  public abstract Class getType();

  public AbstractResponse readResponse() {
    ObjectMapper mapper = new ObjectMapper();
    AbstractResponse response;
    try {
        return (AbstractResponse) mapper.readValue(data, getType());
    } catch (IOException e) {...}
  }
}

public class ResponseAClient extends AbstractClient {
  public Class getType() {
    return ResponseA.class;
  }
}

public class ResponseBClient extends AbstractClient {
  public Class getType() {
    return ResponseB.class;
  }
}
除了作为JSON POJO之外,

ResponseAResponseB没有任何共同之处。如您所见,我使用空的抽象类AbstractResponse来避免客户端类readResponse()ResponseAClientResponseBClient的重复代码。

我的问题

对类似的情况使用空的抽象类是不好的做法,如果是这样,那么编码它的最佳方法是什么?我曾考虑使用泛型,但我看到许多警告不鼓励使用Java Generics。

编辑:感谢您快速回复。在@Kayaman的有用评论之后,我想重新解释我的问题:

对于我上面描述的那种情况,是否有比使用空接口/抽象类更好的实现。拥有一个空接口/抽象类似乎是不好的做法。

2 个答案:

答案 0 :(得分:14)

使用界面。使用空的抽象类是没有意义的(除非你想阻止类继承另一个类)。

至于你的许多警告,不鼓励使用Java Generics。",我很高兴看到一些链接,因为那不是真的。

编辑:通用方法可以为您提供类似以下内容(Response是一个空接口,用于标记具体响应类并限制Client可以处理的允许类型

public class Client<T extends Response> {
    private Class<T> clazz;
    public Client(Class<T> clazz) {
        this.clazz = clazz;
    }
    public T readResponse() {
        ObjectMapper mapper = new ObjectMapper();

        return (T) mapper.readValue(data, clazz);
    }
}

允许您处理强类型的响应。

Client<ResponseA> clientA = new Client<>(ResponseA.class);
ResponseA resp = clientA.readResponse();

问题的答案&#34;什么是空抽象类的好方法&#34;是&#34;重构和重新设计&#34;。

答案 1 :(得分:0)

我宁愿使用带有@Retention(RetentionPolicy.RUNTIME)的注释,而不是使用空接口或抽象类。这是要编写的更多代码,并且可能不是特别易读和快速(您要检查类是否具有此批注的部分)。

语言中有空接口,例如Serializable。但是从Java 5开始它就不再那么有意义了。

import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public abstract class AbstractClient {
    public abstract Class getType();

    public Object readResponse() {
        ObjectMapper mapper = new ObjectMapper();
        try {
            Object response = mapper.readValue(data, getType());

            if (response.getClass().getDeclaredAnnotation(Response.class) == null) {
                // Not a valid type
            }

            return response;
        } catch (IOException e) {...}
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Response {

}

@Response
class ResponseA extends AbstractResponse {
    // JSON POJO
}

@Response
class ResponseB extends AbstractResponse {
    // JSON POJO
}


class ResponseAClient extends AbstractClient {
    public Class getType() {
        return ResponseA.class;
    }
}

class ResponseBClient extends AbstractClient {
    public Class getType() {
        return ResponseB.class;
    }
}