Можете ли вы написать класс Java с ABCL?
Есть ли способ создать класс Java с ABCL (который расширяет другой класс)?
2 ответа
Можно написать непосредственно написать класс Java как байт-код JVM через функции в пакете JVM, который является кодом, который использует собственный компилятор ABCL. Начиная с abcl-0.25.0, есть неподдерживаемый код для метода JAVA:JNEW-RUNTIME-CLASS, который позволяет динамически писать класс Java, который вызывает методы Lisp для выполнения. В коде используются классы из 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);
}
Следующий код на Лиспе создает используемый Java Proxy в текущей JVM:
(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());
...
В этом примере показано, как реализовать интерфейс Java в ABCL.