我对同一种物体有许多不同的表现形式;我们称之为事物。 “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方法。有更简单的方法吗?
答案 0 :(得分:3)
我能想到的两种简单方法:
答案 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的方面和操作,无论它发生什么。