简体   繁体   English

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

[英]What is a good alternative to using an empty abstract class?

Suppose I have the following: 假设我有以下内容:

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;
  }
}

ResponseA and ResponseB have nothing in common besides being a JSON POJO. 除了作为JSON POJO之外, ResponseAResponseB没有任何共同之处。 As you can see I am using an empty abstract class AbstractResponse to avoid duplicated code for readResponse() in the client classes ResponseAClient and ResponseBClient . 正如您所看到的,我使用一个空的抽象类AbstractResponse来避免客户端类ResponseAClientResponseBClient中的readResponse()重复代码。

My question : 我的问题

Is it bad practice to use an empty abstract class for similar cases and if so, what would be the best way to code this? 对类似的情况使用空的抽象类是不好的做法,如果是这样,那么编码它的最佳方法是什么? I have thought about using generics but I've seen many warnings that discourage the use of Java Generics. 我曾考虑使用泛型,但我看到很多警告不鼓励使用Java Generics。

Edit: Thanks for the quick response guys. 编辑:谢谢你的快速反应。 After the useful comments from @Kayaman I'd like to rephrase my question like this: 在@Kayaman的有用评论之后,我想重新解释我的问题:

Is there a better implementation for the kind of situation I've described above than using an empty interface/abstract class. 对于我上面描述的那种情况,是否有比使用空接口/抽象类更好的实现。 It just seems like bad practice to have an empty interface/abstract class. 拥有一个空接口/抽象类似乎是不好的做法。

Use an interface. 使用界面。 There's no sense in using an empty abstract class (unless you want to prevent the classes from subclassing another class). 使用空的抽象类是没有意义的(除非你想阻止类继承另一个类)。

As for your "many warnings that discourage the use of Java Generics.", I'd be happy to see some links, because that's just not true. 至于你的“许多不鼓励使用Java Generics的警告。”,我很高兴看到一些链接,因为那是不正确的。

Edit: A generic approach could give you something like the following ( Response is an empty interface for marking concrete response classes and limiting the allowed types that Client can handle) 编辑:通用方法可以提供类似以下内容( 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);
    }
}

Allowing you to handle responses that are strongly typed. 允许您处理强类型的响应。

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

So the answer to the question "What's a good alternative to an empty abstract class" is "Refactor and Redesign". 因此,“对一个空的抽象类有什么好的替代”这个问题的答案是“重构和重新设计”。

Instead of using an empty interface or abstract class, I'd rather use an annotation with @Retention(RetentionPolicy.RUNTIME) . 我宁愿使用带有@Retention(RetentionPolicy.RUNTIME)的注释,而不是使用空接口或抽象类。 That is a little more code to write though, and may not be especially readable and fast (the part where you want to check if a class has this annotation). 这是要编写的更多代码,并且可能不是特别易读和快速(您要检查类是否具有此批注的部分)。

There are empty interfaces in the language, like Serializable . 语言中有空接口,如Serializable But since Java 5 it doesn't make too much sense anymore. 但是从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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM