Next: Next-method, Previous: Extending Primitives, Up: Methods and Generic Functions [Contents][Index]

GOOPS generic functions and accessors often have short, generic names.
For example, if a vector package provides an accessor for the X
coordinate of a vector, that accessor may just be called `x`

. It
doesn’t need to be called, for example, `vector:x`

, because
GOOPS will work out, when it sees code like `(x `

, that
the vector-specific method of `obj`)`x`

should be called if `obj` is
a vector.

That raises the question, though, of what happens when different
packages define a generic function with the same name. Suppose we work
with a graphical package which needs to use two independent vector
packages for 2D and 3D vectors respectively. If both packages export
`x`

, what does the code using those packages end up with?

duplicate binding handlers explains how
this is resolved for conflicting bindings in general. For generics,
there is a special duplicates handler, `merge-generics`

, which
tells the module system to merge generic functions with the same name.
Here is an example:

(define-module (math 2D-vectors) #:use-module (oop goops) #:export (x y ...)) (define-module (math 3D-vectors) #:use-module (oop goops) #:export (x y z ...)) (define-module (my-module) #:use-module (oop goops) #:use-module (math 2D-vectors) #:use-module (math 3D-vectors) #:duplicates (merge-generics))

The generic function `x`

in `(my-module)`

will now incorporate
all of the methods of `x`

from both imported modules.

To be precise, there will now be three distinct generic functions named
`x`

: `x`

in `(math 2D-vectors)`

, `x`

in ```
(math
3D-vectors)
```

, and `x`

in `(my-module)`

; and these functions
share their methods in an interesting and dynamic way.

To explain, let’s call the imported generic functions (in ```
(math
2D-vectors)
```

and `(math 3D-vectors)`

) the *ancestors*, and the
merged generic function (in `(my-module)`

), the *descendant*.
The general rule is that for any generic function G, the applicable
methods are selected from the union of the methods of G’s descendant
functions, the methods of G itself and the methods of G’s ancestor
functions.

Thus ancestor functions effectively share methods with their
descendants, and vice versa. In the example above, `x`

in
`(math 2D-vectors)`

will share the methods of `x`

in
`(my-module)`

and vice versa.^{29} Sharing is
dynamic, so adding another new method to a descendant implies adding it
to that descendant’s ancestors too.

But note that `x`

in
`(math 2D-vectors)`

doesn’t share methods with `x`

in
`(math 3D-vectors)`

, so modularity is still preserved.