I honestly can't think of a language that even support overloading of methods based on run time types.
And the moment you don't have overloaded methods based on run time types you have to do something interesting like this to do the work.
I honestly can't think of a language that even support overloading of methods based on run time types.
And the moment you don't have overloaded methods based on run time types you have to do something interesting like this to do the work.
Dylan allows sealing of generic functions to limit extensibility where needed and can use that information (along with other information) to optimize, generate warnings, etc.
define class <weapon> (<object>) end;
define class <sword> (<weapon>) end;
define class <wand> (<weapon>) end;
define class <person> (<object>) end;
define class <wizard> (<person>) end;
define class <warrior> (<person>) end;
define method wield (who :: <wizard>, what :: <wand>) => ()
...
end;
define method wield (who :: <warrior>, what :: <sword>) => ()
...
end;Clojure does with multimethods ( http://clojure.org/runtime_polymorphism ). I suspect lisp with meta object protocol does too, but I only heard about it, so can't confirm.
EDIT: deleted my solution that worked without method overloading at all, cause I missed some constraints.
(derive ::wizard ::person)
(derive ::warior ::person)
(derive ::weapon ::thing)
(derive ::dagger ::weapon)
(derive ::sword ::weapon)
(derive ::staff ::weapon)
;; defines dispatch function that returns (inheritable) categories to dispath
;; it's very simple in this case
(defmulti wield! (fn [p1 p2 thing]
[(type p2) (type thing)]))
(defmethod wield! [::person ::thing] [p1 p2 thing]
(say! p1 p2 " refuse"))
(defmethod wield! [::person ::dagger] [p1 p2 thing]
(take! p2 p1 thing)
(say! p1 p2 "accepts."))
(defmethod wield! [::wizard ::staff] [p1 p2 thing]
(take! p2 p1 thing)
(say! p1 p2 " gladly accepts."))
(defmethod wield! [::warrior ::sword] [p1 p2 thing]
(take! p2 p1 thing)
(say! p1 p2 " gladly accepts."))
It obviously could be done in half the lines without using multimethods, but the result would be much less extensible.BTW, with just 2 lines you can add gandalf and it just works (because there are no conflicting methods right now).
(derive ::gandalf ::wizard)
(derive ::gandalf ::warrior)
If there were any - you can set preferences to avoid errors.Now, what happens when a vampire or a werewolf bites a warrior? Here is a rough sketch:
(unless (typep target 'werewolf) (with-scheduling ...))