5

有没有办法用ABCL创建一个 Java 类(扩展另一个类)?

4

2 回答 2

5

可以通过JVM包中的函数直接将Java类编写为JVM字节码,这是ABCL自己的编译器使用的代码。从 abcl-0.25.0 开始,JAVA:JNEW-RUNTIME-CLASS 方法的代码不受支持,该方法允许动态编写调用 Lisp 方法执行的 Java 类。该代码使用来自 ObjectWeb ASM BCEL的类,这些类必须存在于 JVM 类路径中。究竟需要哪个版本的 ASM BCEL 库,以及它是否适用于当前的 ABCL,都未经测试。ABCL 问题#153跟踪了在当代 ABCL 实施中支持这一点所需的工作。

但是如果一个人有一个现有的 Java 接口,希望使用基于 Lisp 的方法来提供一个实现,那么这个过程会相当简单(并且受支持!)

相关函数是 JAVA:JINTERFACE-IMPLEMENTATION,其用法在BankAccount 示例中进行了演示。

对于定义为的 Java 接口

public interface BankAccount {
  public int getBalance();
  public void deposit(int amount);
  public void withdraw(int amount); 
}

以下 Lisp 代码在当前 JVM 中创建了一个可用的 Java 代理:

 (defparameter *bank-account-impl*
  (let ((balance 1000))
    (jinterface-implementation
     "BankAccount"

     "getBalance" 
       (lambda ()
         balance)
     "deposit" 
       (lambda (amount) 
         (let ((amount (jobject-lisp-value amount)))
           (setf balance (+ balance amount))))  
     "withdraw" 
       (lambda (amount)
         (let ((amount (jobject-lisp-value amount)))
           (setf balance (- balance amount)))))))

要从 Java 中获取对此实现的引用,可以使用 BankMainAccount.java 中的代码

  ...
  org.armedbear.lisp.Package defaultPackage
    = Packages.findPackage("CL-USER");
  Symbol bankAccountImplSymbol
    = defaultPackage.findAccessibleSymbol("*BANK-ACCOUNT-IMPL*");
  LispObject value = bankAccountImplSymbol.symbolValue();
  Object object =  ((JavaObject) value).getObject();
  BankAccount account = (BankAccount) object;
  System.out.println("Initial balance: " + account.getBalance());
  account.withdraw(500);
  System.out.println("After withdrawing 500: " + account.getBalance());
  ... 
于 2011-01-26T10:13:28.013 回答
0

这个例子展示了如何在 ABCL 中实现一个 Java 接口。

于 2011-01-25T03:57:03.870 回答