从类调用实现的接口覆盖方法

时间:2014-09-25 21:21:55

标签: java class inheritance interface

我开始用Java做一些高级的事情(对我来说是先进的xD)。

我有这个:

interface ResultSet {
    public void close();
}

class DbResult {
    ResultSet data;
    Statement statement;

    public void close() {
        this.data.close();
        this.statement.close();
    }
}

我试图这样做:

interface ResultSet { //I think that is abstract or something
    public void close();
}

abstract class DbResult implements ResultSet {
    Statement statement;

    @Override
    public void close() {
        super.close();
        this.statement.close();
    }
}

显然它不起作用,因为ResultSet不是超类。我还尝试使DbResult成为一个接口并扩展ResultSet,但它告诉我接口方法不能有一个主体,所以我不知道如何做到这一点。

我试图这样做,所以我可以关闭结果语句,结果只有一个变量而不是2,所以不会因为忘记关闭语句而导致内存泄漏。

Database类以这种方式查询数据库:

class Database {
    private Connection connection;

    /* Here a constructor that
       inits the connection and such things */

    public DbResult query(String q) {
        Statement statement = this.connection.createStatement();
        DbResult result = (DbResult)statement.executeQuery(q);
        result.statement = statement;
        return result;
    }

修改 好吧,既然我知道我不知道我是否能以一种黑客的形式做到这一点,我想:

有没有办法检查是否在类中调用了不存在的方法,捕获它并在另一个变量中调用该方法名?

例如,ResultSet有一个名为getString()的方法。我想知道是否可以调用DbResult.getString("blah");,而DbResult会将该方法重定向到this.data,但是在DbResult类中实现getString方法。

我想知道是否可行,因为ResultSet中有大量函数,而调用DbResult.data.METHOD不如DbResult.METHOD优雅。

3 个答案:

答案 0 :(得分:1)

也许您想要使用的是抽象类而不是接口,例如:

interface A2 {
   void foo();    
   void otherAbstractMethod();
}

abstract class AbstractA2 implements A2 {
  @Override // implemented metthod
  public void foo() {
     System.out.println("From the default method");
  }

  @Override //unimplemented abstract method
  public abstract void otherAbstractMethod();
}

class B2 extends AbstractA2 {

   @Override
   public void foo() {
       super.foo();
       System.out.println("From the override");
   }

   @Override
   public void otherAbstractMethod() {
      // TODO add some code      

      // the line below won't compile
      // super.otherAbstractMethod();  
   }
}

并测试它

public class TestA {
   public static void main(String[] args) {
      A2 myA = new B2();
      myA.foo();
   }
}

修改
关于你的问题的变化,哪些变化一切并且彻底改变,我再次感到困惑。 ResultSet 是您的接口,还是您尝试实现java.sql.ResultSet?如果是后者,您的代码将充满困难,因为您的类无法扩展,并且无法替代查询返回的ResultSet的实际类型。我没有看到您使用合成和继承的替代品。换句话说,继续你最初做的事情 - 创建包含ResultSet字段但不是实现接口的字段。

请注意,如果使用Decorator Pattern,则可以实现ResultSet。有了这个,你就可以创建自己的类,这是一个&#34;包装器&#34;对于原始类型,要求您使用合成继承,并为接口创建所有需要的方法,然后将它们委托给ResultSet组件。< / p>

  

例如,ResultSet有一个名为getString()的方法。我想知道是否可以调用DbResult.getString(&#34; blah&#34;);并且DbResult会将该方法重定向到this.data,但是在DbResult类中实现getString方法。

不,你必须在你的子装饰器类中实现所有这些方法。

答案 1 :(得分:1)

猜猜:它已经是Java的一部分(从版本7开始):

Java API Documentation: java.lang.AutoCloseable

public interface AutoCloseable {
   void close();
}

ResultSetStatement(以及许多其他类)已经实现了此接口。 最好的事情是:try在try语句中管理的资源是automatically closed, if they implement this interface

答案 2 :(得分:1)

  

是否有办法检查是否调用了不存在的方法   在类中,捕获它并在另一个变量中调用该方法名称?

因此,您希望将调用包装到实例而不必扩展它或实现其每个方法,这实际上是可行的,但仅适用于通过接口公开的方法。 好消息是ResultSet实际上是一个界面。

这可以通过动态代理来完成(请参阅ProxyInvocationHandler)。

您可以创建由Proxy支持的InvocationHandler,其中包含ResultSet。对您的代理实例的任何调用都将委派给InvocationHandlerResultSet可以直接处理它们,或者在您的情况下,将它们委托给包装的实际public class MyResultSetInvocationHandler implements InvocationHandler { private final ResultSet wrappedResultSet; private MyResultSetInvocationHandler(ResultSet resultSet) { wrappedResultSet = resultSet; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // call method on delegate Object result = method.invoke(wrappedResultSet, args); // optionally do something with the result, and return it afterwards return result; } catch (Throwable ex) { // handle exception, or rethrow it throw ex; } } /** * Factory method, creates a dynamic proxy wrapping the given result set. */ public static ResultSet wrap(ResultSet delegate) { MyResultSetInvocationHandler handler = new MyResultSetInvocationHandler(delegate); return (ResultSet) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { ResultSet.class }, handler); } } 实例。

// the actual result set
ResultSet resultSet = ...

// and your wrapped proxy/handler as a surrogate
resultSet = MyResultSetInvocationHandler.wrap(resultSet);

用法:

{{1}}