对最后一堂课进行细分;或者,一个堕落的装饰者

时间:2009-12-06 03:54:30

标签: java decorator subclass final

我对同一种物体有许多不同的表现形式;我们称之为事物。 “Thing”是一个标记界面。 ThingFormat0,ThingFormat1,ThingFormat2等都是实现Thing的JavaBeans。 (因为它们是JavaBeans,JSON marshaller会自动将它们自动转换为JSON和从JSON转换。)ThingFormat1只有少数成员,如name和id。 ThingFormat2具有到其他东西的URI链接。在ThingFormat3中有ThingFormat1表示其他东西等。

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

我希望ThingFormat0的行为类似于URI,但实现了标记接口Thing。

public class ThingFormat0 extends URI implements Thing {}

这不起作用,因为URI是最终类,不能被子类化。

我能想到的唯一方法就是制作一个装饰器(一种非常简单的装饰器,因为它不会向URI添加任何功能)。这在一些“鸭式”语言中很容易,但更多的是Java的痛苦,因为我必须包装一个URI并实现我需要的所有URI方法。有更简单的方法吗?

5 个答案:

答案 0 :(得分:3)

我能想到的两种简单方法:

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

答案 1 :(得分:2)

该类是否有任何理由不能使用合成而不是继承?

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

答案 2 :(得分:1)

您无法继承最终类。周期。

在URI的情况下,出于安全原因,它几乎肯定是最终的;即通过提供一个偷偷摸摸的URI子类(例如)允许它破坏访问控制来阻止某人破坏沙盒安全性。

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

答案 3 :(得分:0)

// base class that handles delegation
class BaseThing implements Thing {

   BaseThing(String uri) { ... }

   BaseThing(URI uri) { ... }

   URI getURI() { ... }

   ...
}

class ThingFormat0 extends BaseThing {
   ...
}

答案 4 :(得分:0)

您发现这很困难,因为您的ThingFormat类型不是 URI。它们公开URI并且可以对应URI,但这不会使它们成为URI。也许你正在为实现继承而苦恼,但是接口继承在这里失败了,因为这不是一个正确的 is-a 关系;它没有通过LSP

例如,考虑ThingFormat是否具有方案或片段组件,或者是否可以针对某个基URI解析一个。这些是与ThingFormat无关的URI的方面和操作,无论它发生什么。