簡體   English   中英

從類調用實現的接口覆蓋方法

[英]Call implemented interface overriden method from a class

我開始用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;
    }

編輯:好的,現在我知道我不能想知道我是否可以用hackish形式做到這一點我:

有沒有辦法檢查是否在類中調用了不存在的方法,捕獲它並在另一個變量中調用該方法名稱?

例如, ResultSet有一個名為getString()的方法。 我想知道是否可以調用DbResult.getString("blah"); 並且DbResult會將該方法重定向到this.data但是在DbResult類中實現getString方法。

我想知道是否可行,因為ResultSet有大量函數,並且調用DbResult.data.METHOD不如DbResult.METHOD優雅。

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

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字段的類,但不創建實現接口的字段。

請注意,如果使用裝飾器模式,則可以實現ResultSet。 有了這個,您將創建自己的類,它是原始類型的“包裝器”, 它將要求您使用組合繼承,並為接口創建所有需要的方法,然后將它們委托給ResultSet組件。

例如,ResultSet有一個名為getString()的方法。 我想知道是否可以調用DbResult.getString(“blah”); 並且DbResult會將該方法重定向到this.data,但是在DbResult類中實現getString方法。

不,你必須在你的子裝飾器類中實現所有這些方法。

猜猜看:它已經是Java的一部分 (從版本7開始):

Java API文檔:java.lang.AutoCloseable

public interface AutoCloseable {
   void close();
}

ResultSetStatement (以及許多其他類)已經實現了此接口。 最重要的事:被管理的資源try在一個try語句被自動關閉,如果他們實現了這個接口

有沒有辦法檢查是否在類中調用了不存在的方法,捕獲它並在另一個變量中調用該方法名稱?

因此,您希望將調用包裝到實例而不必擴展它或實現其每個方法,這實際上是可能的,但僅適用於通過接口公開的方法。 好消息是ResultSet實際上是一個接口。

這可以通過動態代理來完成(請參閱ProxyInvocationHandler )。

您可以創建由InvocationHandler支持的Proxy ,該InvocationHandler包裝ResultSet 對代理實例的任何調用都將委托給InvocationHandler ,它可以直接處理它們,或者在您的情況下,將它們委托給包裝的實際ResultSet實例。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM