我经常希望能够正确地装饰java类,即向它们添加行为。我知道来自红宝石的混合物,我知道它们会非常混乱。
我提出了这样一种语言结构的理论思想:
package org.test.decorator;
public decorator ListPatch<E> extends List<E> {
public E last() {
return this.get(this.size() - 1);
}
}
this
可以访问List
和Decorator本身的公共成员。
然后在课堂上我可以使用:
package org.test.decorator;
decoration org.test.decorator.ListPatch;
public MyClass {
public void foo() {
List<String> list = Lists.newArrayList();
list.add("test");
System.out.println(list.last());
}
}
我对编译器知之甚少,所以我想知道这样的事情是否可行。如果它确实会有所改善。
答案 0 :(得分:2)
当然,这是可能的。
Scala编译为字节码(并且具有从Scala类到字节码类的相当直接的映射)并支持mixins这一事实证明了这一点。
以下是您的示例代码在Scala语法中的外观:
class ListTest {
// ...
}
trait ListPatch {
def last {
// ...
}
}
object Main {
def main(args: Array[String]) {
val list = new ListTest() with ListPatch;
list.add("test")
println(list.last)
}
}
Scala通过添加组成Main$$anon$1
和ListTest
的腋下类ListPatch
来编译它。
Java开发人员的座右铭一直是(并且可能永远都是)“如果有疑问,请将其删除。”尽管如此。
相关问题:
答案 1 :(得分:1)
不是你的问题的答案,但你可以通过控制/依赖注入的反转来解决这个问题(就像你在代码中所做的那样)
基本上是: 不要使用“new ArrayList()”而是使用像“injector.new(ArrayList.class)”这样的工厂。此注入器现在可以覆盖所需的类并返回一个Object,该Object扩展了使用您的方法修饰的ArrayList。
答案 2 :(得分:1)
您的想法听起来很像Extension methods in C#。
扩展方法使您可以向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。
在C#中你会把你的例子写成:
public static class ListExtensions
{
public E Last(this List<E> list)
{
return list[list.Count - 1];
}
}
像这样使用它:
List<String> list = new List<String>();
list.Add("test");
Console.WriteLine(list.Last());
因此,从设计角度来看,它当然可以设计和添加。但是,在向现有语言添加内容时会有其他一些注意事项,例如语法冲突,向后兼容性,边缘情况,设计和编码成本与其提供的好处。
Eric Lippert在C#中有a great blog about Extension Properties(扩展方法的自然扩展),在第二部分中,他强调了影响为什么产品X没有Y功能的一些方面?,我肯定也适用于Java及其开发。