Java 将最后一个类划分为子类;或者,堕落的装饰师

Java 将最后一个类划分为子类;或者,堕落的装饰师,java,decorator,subclass,final,Java,Decorator,Subclass,Final,我对同一类物体有许多不同的表示;让我们称之为一件事。“Thing”是一个标记接口。ThingFormat0、ThingFormat1、ThingFormat2等都是实现Thing的JavaBean。(因为它们是JavaBean,JSON封送器会自动将它们转换为JSON,并自动将它们转换为JSON。)ThingFormat1只有几个成员,如name和id。ThingFormat2有指向其他内容的URI链接。在ThingFormat3中,ThingFormat1表示其他事物等 JSON序列化程序知道

我对同一类物体有许多不同的表示;让我们称之为一件事。“Thing”是一个标记接口。ThingFormat0、ThingFormat1、ThingFormat2等都是实现Thing的JavaBean。(因为它们是JavaBean,JSON封送器会自动将它们转换为JSON,并自动将它们转换为JSON。)ThingFormat1只有几个成员,如name和id。ThingFormat2有指向其他内容的URI链接。在ThingFormat3中,ThingFormat1表示其他事物等

JSON序列化程序知道如何自动转换URI。(它适用于任何可以使用toString()和构造函数类名(String)进行转换的类。)

我想要一个ThingFormat0,它的行为类似于URI,但实现了标记接口

public class ThingFormat0 extends URI implements Thing {}
这不起作用,因为URI是最后一个类,不能被子类化


我能想到的唯一方法是制作一个decorator(一种非常退化的decorator,因为它不向URI添加任何功能)。这在一些“duck类型”语言中很容易,但在Java中更麻烦,因为我必须包装一个URI并实现我需要的所有URI方法。有更简单的方法吗?

您不能对最终类进行子类化。句号

就URI而言,出于安全原因,它几乎肯定是最终的;i、 e.通过提供一个(例如)允许其破坏访问控制的偷偷摸摸的URI子类型来阻止某人破坏沙箱安全


所以,是的,你需要使用包装器或装饰器之类的东西。

我可以想到两种简单的方法:

  • 如果使用Eclipse,则可以自动生成任何字段的委托方法
  • 将URI的源复制到名为ThingURI的新类中

类不能使用组合而不是继承有什么原因吗

public class ThingFormat0 implements Thing {
  private final URI uri;

  public ThingFormat0(String uri) { this.uri = URI.create(uri); }

  public ThingFormat0(URI uri) { this.uri = uri; }

  public URI getUri() { return uri; }

  @Override public String toString() {
    return uri.toString();
  }
}

您发现这很困难,因为您的
ThingFormat
类型不是URI。它们公开URI并可以对应于URI,但这并不意味着它们是URI。也许您渴望实现继承,但是接口继承在这里失败了,因为这不是一个正确的is-a关系;它失败了


例如,考虑
ThingFormat
是否有一个方案或片段组件,或者是否可以根据某个基本URI解析一个方案或片段组件。这些都是uri的方面和操作,与
ThingFormat
没有太大关系,不管它做什么。

当Thing是我的响应类的一个成员时,响应的JSON序列化是{“Thing”:{“uri”:“}}而不是{“Thing”:”}。
// base class that handles delegation
class BaseThing implements Thing {

   BaseThing(String uri) { ... }

   BaseThing(URI uri) { ... }

   URI getURI() { ... }

   ...
}

class ThingFormat0 extends BaseThing {
   ...
}