鑑於szenario提供了一個基本包,它可以通過類和另一個想要擴展此功能的包來表示某些內容。如何從外部程序包中重載方法
(defpackage :test
(:use :cl)
(:nicknames :test)
(:export a-test-class
method-a
slot-a))
(in-package :test)
(defclass a-test-class()
((slot-a
:initform 42
:reader slot-a)))
(defmethod method-a ((a-test-class a-test-class))
(setf (slot-value a-test-class 'slot-a) 21)
a-test-class)
(defpackage :exttest
(:use :cl)
(:export extended-a-test-class
method-a))
(in-package :exttest)
(defclass extended-a-test-class (test:a-test-class)
((slot-b
:reader slot-b
:initform nil)))
(defmethod method-a ((a-test-class extended-a-test-class))
(setf (slot-value a-test-class 'slot-a) 23)
a-test-class)
現在,我得到它並沒有真正做anthying但過去的a-test-class
和extended-a-test-class
實例的列表,應該呼籲所有的人method-a
,希望他們改變,分別以自己的類型的函數。例如。 (slot-a (method-a a-test-class-instance)) > 21
和(slot-a (method-a extended-a-test-class-instance)) > 23
但試圖做到這一點,我碰上的正確調用方法,一個問題是:
(defparameter *test-instance* (make-instance 'test:a-test-class))
(defparameter *ext-test-instance* (make-instance 'exttest:extended-a-test-class))
(test:slot-a (test:method-a *test-instance*))
> 21
(test:slot-a (test:method-a *ext-test-instance*))
> 21
或
(test:slot-a (exttest:method-a *test-instance*))
(test:slot-a (exttest:method-a *ext-test-instance*))
debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {1002B03193}>:
There is no applicable method for the generic function
#<STANDARD-GENERIC-FUNCTION EXTTEST:METHOD-A (1)>
when called with arguments
(#<TEST:A-TEST-CLASS {10041148A3}>)
既不是真正的工作對我來說,在無論哪種方式我都無法編譯,或者方法的效果不符合要求。如果類和方法定義在同一個包中,但一切正常。
因此:如何在不需要訪問相應軟件包的情況下調用實例上的方法?(如果我不能這樣做,我想知道我在共Lisp的面向對象編程的期望如何被誤導)
對於「工作」例如,輸出什麼我想像,我編碼這個C++程序。我知道CLOS的工作方式不同於「通用」的面向對象系統,因爲方法不屬於類。但是我希望任何面向對象的系統(在某種程度上)能夠表現/這樣來使用:
#include <iostream>
namespace test {
class sub {
public:
virtual sub* method_a() = 0;
};
class a_test_class : public sub
{
protected:
int value;
public:
a_test_class(int val) : value(val) {
}
a_test_class* method_a() {
value = 21;
return this;
}
int get_value() {
return value;
}
};
}
namespace exttest {
class extended_a_test_class : public test::a_test_class {
public:
extended_a_test_class(int val) : a_test_class(val) { }
extended_a_test_class* method_a() {
std::cout << "calling overloaded method" << std::endl;
this->value = 23;
return this;
}
};
}
int main(int argc,const char* argv[]) {
test::a_test_class* atc = new test::a_test_class(42);
test::a_test_class* eatc = new exttest::extended_a_test_class(42);
std::cout << atc->method_a()->get_value() << std::endl;
std::cout << eatc->method_a()->get_value() << std::endl;
delete atc;
delete eatc;
}
> ./a.out
21
calling overloaded method
23
方法可能不屬於類,但它們屬於通用函數。我發現在爲它們定義方法之前定義泛型函數(使用'defgeneric')通常是有幫助的。至少SBCL還會在您使用'defmethod'隱式創建泛型函數時發出警告。這可能會幫助你。 – Svante
@Svante我確實看到有新的泛型方法被定義,但我不知道如何防止。但仍然是一個有價值的建議,謝謝。 – Sim