1

我经常希望能够正确地装饰 java 类,即为它们添加行为。我知道来自 ruby​​ 的 mixin,而且我知道它们会变得非常混乱。

我想出了这样一个语言结构的理论想法:

package org.test.decorator;

public decorator ListPatch<E> extends List<E> {
    public E last() {
        return this.get(this.size() - 1);
    }
}

this将允许访问公共成员List和装饰器本身。

然后在我可以使用的课程中:

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

我对编译器没有太多了解,所以我想知道这样的事情是否可能。此外,如果它实际上将是一个改进。

4

3 回答 3

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组成ListTestListPatch.

Java 开发人员的座右铭一直是(并且很可能永远是)“如果有疑问,请忽略它”。尽管。

相关问题:

于 2012-07-29T21:55:27.173 回答
1

不是您问题的真正答案,但您可以通过控制/依赖注入反转来解决此问题(就像您在代码中所做的那样)

基本上:不要使用“new ArrayList()”,而是使用像“injector.new(ArrayList.class)”这样的工厂。这个注入器现在可以覆盖想要的类并返回一个对象,它扩展了用你的方法装饰的 ArrayList。

于 2012-07-29T21:57:40.693 回答
1

您的想法听起来很像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# 中的扩展属性(扩展方法的自然扩展),在第二部分中,他强调了影响产品 X 为什么没有功能 Y 的一些方面?,我确信这也适用于 Java 及其开发。

于 2012-07-29T21:59:11.443 回答