首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure:有可能继承用:gen-class定义的类的状态吗?

Clojure:有可能继承用:gen-class定义的类的状态吗?
EN

Stack Overflow用户
提问于 2018-11-06 11:33:22
回答 1查看 207关注 0票数 1

我正在尝试学习一些Java库,并将Clojure作为一种工作语言。这个库(在Java中通常是如此)非常面向对象,需要客户端代码中的类层次结构。我定义了一个从库类继承的类,并使用一些额外的方法和数据作为可变字典存储在state字段中:

代码语言:javascript
复制
(: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继承的子类。

代码语言:javascript
复制
(: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实例调用ChildClass宏时,会得到一个空指针异常-- :state定义的字段不是继承的,字典中也没有键:library-object-one

快速修正是在子类中重新定义-init函数,如下所示:

代码语言:javascript
复制
(defn -init []
  [[] (ref {:library-object-one (LibraryObjectOne.)
            :library-object-two (LibraryObjectTwo.)})])

(即从父类复制初始化代码)。但这是对干燥原则的严重违反。是否有从父类继承状态的方法?

据我所知,这根本不是一种习语,也是对:gen-class API的滥用,它只为互操作性目的而提供。也许我不应该在我这一边使用继承,我必须以某种非面向对象的方式实现多态性(例如,修改存储在state字典中的函数和值)。如果是真的,我在哪里可以看到这种方法的好例子呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-06 20:32:12

您不必为子类提供:state。如果不这样做,它只会调用父方法。

代码语言:javascript
复制
(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)

以及调用名称空间:

代码语言:javascript
复制
(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}

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53171063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档