Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在实现接口但不扩展另一个类的Java类中引用超级方法?_Java_Generics_Inheritance_Design Patterns_Generic Collections - Fatal编程技术网

如何在实现接口但不扩展另一个类的Java类中引用超级方法?

如何在实现接口但不扩展另一个类的Java类中引用超级方法?,java,generics,inheritance,design-patterns,generic-collections,Java,Generics,Inheritance,Design Patterns,Generic Collections,我有几个Java类,它们扩展了通用列表接口的各种实现。他们只需记录添加到列表中的任何内容 LogginArrayList如下所示。顾名思义,它扩展了ArrayList。LoggingLinkedList类除了扩展LinkedList之外是相同的 我的主要目标是避免为了使用不同的基类而复制所有的公共代码。我正在尽可能地坚持干燥原则(不要重复你自己) 首先,请不要建议更好的登录方式。那根本不是我真正的申请。这只是演示我遇到的问题的一种简单方法 我有两个密切相关的问题。第一个问题是标题中的问题。如何在

我有几个Java类,它们扩展了通用列表接口的各种实现。他们只需记录添加到列表中的任何内容

LogginArrayList如下所示。顾名思义,它扩展了ArrayList。LoggingLinkedList类除了扩展LinkedList之外是相同的

我的主要目标是避免为了使用不同的基类而复制所有的公共代码。我正在尽可能地坚持干燥原则(不要重复你自己)

首先,请不要建议更好的登录方式。那根本不是我真正的申请。这只是演示我遇到的问题的一种简单方法

我有两个密切相关的问题。第一个问题是标题中的问题。如何在实现接口但不扩展另一个类的Java类中引用“super”方法

如下所示的LoggingArrayList类工作正常,但当我将类声明从…extends ArrayList更改为…implements List时,对super.method()的三个引用将不再可调用,因此我提出了第一个问题

对我的第二个问题的好回答几乎会使第一个问题变得毫无意义。第二个问题是:有没有一种方法可以声明一个抽象基类或一个接口,该接口使用各种add()方法的默认实现来扩展List,这样我就可以简单地扩展该抽象基类或实现该接口,并且只指定哪种类型的List将作为具体类的基础

例如,我想这样做:

interface LoggingList<T extends Object, L extends List<T>> extends L
{
    // overloaded methods go here as shown below 
    //  with overloaded methods declared as default for the interface
}
接口日志列表扩展了L
{
//重载方法如下所示
//将重载方法声明为接口的默认方法
}
…然后,我可以简单地为列表的每个具体实现实现一次LoggingList,而无需复制所有公共代码。具体的类可能看起来像这样,在它们的花括号中不需要额外的代码:

public class LoggingArrayList<T extends Object> implements LoggingList<T, ArrayList<T>> {}
public class LoggingLinkedList<T extends Object> implements LoggingList<T, LinkedList<T>> {}
公共类LoggingArrayList实现LoggingList{}
公共类LoggingLinkedList实现LoggingList{}
问题是,我提出的接口定义是无效的(不会编译),而且,下面代码中对super.method的引用也不可用,除非我将LoggingList设置为抽象子类而不是接口,然后我就回到了现在的位置

提前感谢你提出的关于如何实现我的目标的想法

这是我的整个LoggingArrayList课程

public abstract class LoggingArrayList<T extends Object>
    extends ArrayList<T>
{
    protected void log(T e)
    {
        System.out.println(e == null ? "null" : e.toString());
    }

    @Override
    public boolean add(T e) {
        log(e);
        // How do I reference a super.method()
        // in a class that implements an interface
        // but does not extend another class?
        return super.add(e);
    }

    @Override
    public boolean addAll(Collection<? extends T> clctn) {
        boolean anyChanges = false;
        for(T e : clctn)
        {
            // ensure that we call our overridden version of add()
            //  so it gets logged.
            anyChanges = anyChanges || add(e);
        }
        return anyChanges;
    }

    @Override
    public boolean addAll(int i, Collection<? extends T> clctn) {
        for(T e : clctn)
        {
            // ensure that we call our overridden version of add() 
            //  so it gets logged.
            add(i, e);
            i++; // keep the inserted elements in their original order
        }
        return !clctn.isEmpty();
    }

    @Override
    public T set(int i, T e) {
        log(e);
        // How do I reference a super.method()
        // in a class that implements an interface
        // but does not extend another class?
        return super.set(i, e);
    }

    @Override
    public void add(int i, T e) {
        log(e);
        // How do I reference a super.method()
        // in a class that implements an interface
        // but does not extend another class?
        super.add(i, e);
    }
}
公共抽象类LoggingArrayList
扩展ArrayList
{
受保护的无效日志(TE)
{
System.out.println(e==null?“null”:e.toString());
}
@凌驾
公共布尔加法(TE){
日志(e);
//如何引用super.method()
//在实现接口的类中
//但是不扩展另一个类吗?
返回super.add(e);
}
@凌驾

public boolean addAll(Collection完成此操作的一种方法是:委托

不必为不同类型的列表提供多个实现,您可以只使用一个

public class LoggingList<T extends Object> implements List<T>

  protected List<T> superList;

  public LoggingList(List<T> anotherList) {
     superList= anotherList;
  }

  protected void log(T e) {
      System.out.println(e == null ? "null" : e.toString());
  }

  @Override
  public boolean add(T e) {
      log(e);
      return superList.add(e);
  }
public类LoggingList实现列表
受保护列表超级列表;
公共日志列表(另一个列表){
超级列表=另一个列表;
}
受保护的无效日志(TE){
System.out.println(e==null?“null”:e.toString());
}
@凌驾
公共布尔加法(TE){
日志(e);
返回超级列表。添加(e);
}
然后,您可以调用
超级列表,而不是调用
超级列表。

您仍然需要将构造函数从
new LoggingLinkedList()
调整为
new LoggingList(new LinkedList());
-但这应该没什么大不了的…

您可以使用它。只需谷歌“如何使用jdk代理类”


仅供将来参考,下面是我使用Sergey Morozov建议的代理方法编写的一个完整的工作解决方案。它的核心代码不到50行。最后包含的一半以上的代码只是对实际功能的单元测试

我还不确定我是否会最终将这种方法用于我的目的,但这是一个非常有用的练习。谢谢你的建议,谢尔盖

public class LoggingListProxyFactory
{
    protected static void log(String methodName, Object element)
    {
        System.out.println(methodName
                + ": ["
                + (element == null ? "null" : element.toString())
                + "]"
        );
    }

    public static <T extends Object> List<T> getProxy(final List<T> list) {
        return (List<T>) Proxy.newProxyInstance(
                list.getClass().getClassLoader(),
                new Class[]{ List.class },
                new LoggingInvocationHandler(list)
        );
    }

    private static class LoggingInvocationHandler<T>
            implements InvocationHandler
    {
        final List<T> underlyingList;

        public LoggingInvocationHandler(List<T> list) {
            this.underlyingList = list;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable
        {
            // These are the List interface methods that we want to log.
            // In every case, the new elements happen to be the last parameter.
            //
            // boolean add(Object e)
            // void add(int index, Object element)
            // boolean addAll(Collection c)
            // boolean addAll(int index, Collection c)
            // Object set(int index, Object element)
            String methodName = method.getName();
            if( ( "add".equals(methodName)
                | "addAll".equals(methodName)
                | "set".equals(methodName)
                )
                // a few additional probably unnecessary checks
                && args != null
                && args.length == method.getParameterCount()
                && method.getParameterCount() > 0
                )
            {
                log(methodName, args[args.length-1]);
            }
            return method.invoke(underlyingList, args);
        }
    }

    public void testGetProxy() {
        List<String>[] testLists = new List[] {
            new ArrayList<>(),
            new LinkedList<>()
        };
        for(List<String> aList : testLists)
        {
            List<String> proxy = LoggingListProxyFactory.getProxy(aList);

//          aList.add(42); // type is enforced at compile time
            aList.add(aList.getClass().getSimpleName());
            aList.add("unlogged");
            aList.add(null);

//          proxy.add(42); // type is enforced at compile time
            proxy.add(proxy.getClass().getSimpleName());
            // exercise each the methods that are being logged
            proxy.add("foo");
            proxy.add(0, "bar");
            proxy.add(null);
            proxy.addAll(aList);
            proxy.addAll(7, aList);
            proxy.set(5, "five");

            System.out.println();
            System.out.println(aList.getClass().getSimpleName()
                    + ".size() = " + aList.size());
            aList.stream().forEach(System.out::println);

            System.out.println();
            System.out.println("proxy.size() = " + proxy.size());
            proxy.stream().forEach(System.out::println);
        }
    }
}
公共类LoggingListProxyFactory
{
受保护的静态无效日志(String methodName,Object元素)
{
System.out.println(methodName
+ ": ["
+(element==null?“null”:element.toString()
+ "]"
);
}
公共静态列表getProxy(最终列表){
返回(列表)Proxy.newProxyInstance(
list.getClass().getClassLoader(),
新类[]{List.Class},
新的LoggingInvocationHandler(列表)
);
}
私有静态类LoggingInvocationHandler
实现调用处理程序
{
最终清单,参考清单;
公共日志处理程序(列表){
this.underyinglist=列表;
}
@凌驾
公共对象调用(对象代理、方法、对象[]参数)
扔掉的
{
//这些是我们要记录的列表接口方法。
//在任何情况下,新元素都恰好是最后一个参数。
//
//布尔加法(对象e)
//void add(int索引,对象元素)
//布尔addAll(集合c)
//布尔addAll(整数索引,集合c)
//对象集(int索引,对象元素)
String methodName=method.getName();
if((“add“.equals(methodName))
|“addAll”.equals(方法名)
|“set”.equals(方法名)
)
//a