java - Clojure:是否可以继承使用 :gen-class 定义的类的状态?
问题描述
我正在尝试使用 Clojure 作为工作语言来研究一些 Java 库。该库(与 Java 中一样)非常面向对象,并且需要客户端代码中的类层次结构。我定义了一个从库类继承的类,其中包含一些额外的方法,并将数据存储为state
字段中的可变字典:
(:gen-class
:name my-project.my-parent-class.MyParentClass
:extends com.example.library.LibraryClass
:methods [[setSomeData [com.example.library.LibraryType] void]]
:exposes-methods {libraryMethodOne parentLibraryMethodOne
libraryMethodTwo parentLibraryMethodTwo}
:init init
:state state))
(defmacro set-field!
[this key value]
`(dosync (alter (.state ~this) assoc ~key ~value)))
(defmacro get-field
[this key]
`(@(.state ~this) ~key))
(defn -init []
[[]
(ref {:library-object-one (LibraryObjectOne.)
:library-object-two (LibraryObjectTwo.)})])
(defn -setSomeData [this t]
(.setSomething (get-field this :library-object-one) t)
… ; (library methods overriding here)
然后我创建了一个继承自我的子类MyParentClass
:
(:gen-class
:name my-project.my-child-class.ChildClass
:extends my-project.my-parent-class.MyParentClass
:exposes-methods {libraryMethodOne myParentClassMethodOne}
:init init
:state state))
(defn -init []
[[] (ref {})])
…
但是当我在方法中为实例调用(get-field this :library-object-one)
宏时出现空指针异常- 定义的字段未继承并且字典中没有键。ChildClass
-setSomeData
:state
:library-object-one
快速而肮脏的修复是重新定义-init
子类中的函数,如下所示:
(defn -init []
[[] (ref {:library-object-one (LibraryObjectOne.)
:library-object-two (LibraryObjectTwo.)})])
(即从父类复制初始化代码)。但这严重违反了 DRY 原则。有没有办法从父类继承状态?
我知道这根本不是一个惯用的 Clojure,而是一种对:gen-class
API 的滥用,它只是为了互操作性目的而提供的。也许我不应该使用继承,我必须以某种非 OOP 方式实现多态性(例如,通过修改存储在state
字典中的函数和值)。如果是真的,我在哪里可以看到这种方法的好例子?
解决方案
您不必:state
为子类提供 a。如果你不这样做,它只会调用父母的方法。
(ns my-project.classes)
(gen-class
:name my_project.my_parent_class.MyParentClass
:init init
:state state)
(defn -init []
[[]
(ref {:library-object-one "foo"
:library-object-two "bar"})])
(gen-class
:name my_project.my_child_class.ChildClass
:extends my_project.my_parent_class.MyParentClass)
和调用命名空间:
(ns my-project.core
(:import (my_project.my_child_class ChildClass))
(:gen-class))
(defn -main [& args]
(let [inst (ChildClass.)]
(println @(.state inst))))
这打印:
{:library-object-one foo, :library-object-two bar}
推荐阅读
- scala - Spark 数据框 - 替换 Scala 中键/值列表中的所有值
- ios - 切换视图后数据丢失
- python - 如何计算具有指定值的文本文件中的行数?
- r - 为什么 filter_at 在 ifelse 中不起作用?
- php - 在 PHP 中使用动态变量作为日期时如何获取下周日的日期?
- google-sheets - 每行中最早日期的 ArrayFormula
- javascript - 我如何在 Input Money Format JS 前面添加 $
- directed-acyclic-graphs - 邻接表 DAG 的有效传递约简
- python - Twitter:引用的推文没有quoted_status 也没有quoted_status_id
- php - 在 laravel 中选择 2 个条件和 while