From: Leo on
Hello there,

I have a custom class like this:

(defclass solver (multi-dimensional-root-solver-f multi-dimensional-root-solver-fdf)
()
(:documentation "A customised class for multidimensional root solver."))

And my constructor like this:

(defun make-solver (function x0 &optional algorithm jacobian jacobian-fdf)
(let* ((object (if jacobian
(make-multi-dimensional-root-solver-fdf
algorithm (list function jacobian jacobian-fdf) x0)
(make-multi-dimensional-root-solver-f algorithm function x0))))
(change-class object 'solver)))

But using change-class is a bad idea, because methods for the
superclasses stopping working on the new SOLVER class.

I am sure there must be a way to re-use constructors from superclasses.
Could someone give me some help? I am beginning programming in CLOS.

Thank you.

Leo
From: Tamas K Papp on
On Tue, 15 Jun 2010 16:17:38 +0100, Leo wrote:

> Hello there,
>
> I have a custom class like this:
>
> (defclass solver (multi-dimensional-root-solver-f
> multi-dimensional-root-solver-fdf)
> ()
> (:documentation "A customised class for multidimensional root
> solver."))
>
> And my constructor like this:
>
> (defun make-solver (function x0 &optional algorithm jacobian
> jacobian-fdf)
> (let* ((object (if jacobian
> (make-multi-dimensional-root-solver-fdf
> algorithm (list function jacobian jacobian-fdf)
> x0)
> (make-multi-dimensional-root-solver-f algorithm
> function x0))))
> (change-class object 'solver)))
>
> But using change-class is a bad idea, because methods for the
> superclasses stopping working on the new SOLVER class.
>
> I am sure there must be a way to re-use constructors from superclasses.
> Could someone give me some help? I am beginning programming in CLOS.

I don't really understand what the problem is. Presumably those
functions call make-instance somewhere - why don't you call that
directly? If objects need initialization (eg slots computed, etc),
you can just use INITIALIZE-INSTANCE :AFTER methods. When you
specialize your class further, just add another one of these, and all
of them will get called.

Tamas
From: Leo on
On 2010-06-15 16:24 +0100, Tamas K Papp wrote:
> I don't really understand what the problem is. Presumably those
> functions call make-instance somewhere - why don't you call that
> directly? If objects need initialization (eg slots computed, etc),
> you can just use INITIALIZE-INSTANCE :AFTER methods. When you
> specialize your class further, just add another one of these, and all
> of them will get called.

I thought of this but reluctant to use it. The definition of one of the
superclass expands into: http://paste.pocoo.org/show/225702/

I can copy the whole chunk of make-instance and change the class name to
mine but that seems pretty ugly.

Leo
From: Captain Obvious on
L> But using change-class is a bad idea, because methods for the
L> superclasses stopping working on the new SOLVER class.

I think the bad idea was inheriting from both.

(defclass solver (multi-dimensional-root-solver-f
multi-dimensional-root-solver-fdf)()

Do you really mean that solver IS BOTH solver-f AND solver-fdf?

As far as I understand from your code solver might be EITHER solver-f OR
solver-fdf.
It is not expressed via inheritance relationship.

I don't really understand why you need your own solver class at all. Just
use one of stock ones.

From: Leo on
On 2010-06-15 20:32 +0100, Captain Obvious wrote:
> L> But using change-class is a bad idea, because methods for the
> L> superclasses stopping working on the new SOLVER class.
>
> I think the bad idea was inheriting from both.
>
> (defclass solver (multi-dimensional-root-solver-f
> multi-dimensional-root-solver-fdf)()
>
> Do you really mean that solver IS BOTH solver-f AND solver-fdf?
>
> As far as I understand from your code solver might be EITHER solver-f
> OR solver-fdf.
> It is not expressed via inheritance relationship.
>
> I don't really understand why you need your own solver class at all.
> Just use one of stock ones.

You are right. I was looking for a way to solve this dilemma:

The routine (defined as fsolve-1 in the example code below) to find the
solution is essentially the same for both classes and I want to avoid
doing:

(defmethod fsolve
((solver multi-dimensional-root-solver-f)
&key (absolute-error 1d-7) (max-iteration 500) print-steps)
(fsolve-1 solver absolute-error max-iteration print-steps))

(defmethod fsolve
((solver multi-dimensional-root-solver-fdf)
&key (absolute-error 1d-7) (max-iteration 500) print-steps)
(fsolve-1 solver absolute-error max-iteration print-steps))

-fdf and -f's have a common superclass that is also the superclass of
many other classes.

Leo