Caveat, I really wouldn’t recommend doing either of these things, they’re brittle (especially the second one) and probably can easily break / lead to bugs. But they are technically possible.
If you’re specializing the arguments of the function beyond the original definition, you can call the original definition with Base.invoke (or the macro form in Julia 1.7):
julia> foo(x::Real) = "original"
foo (generic function with 1 method)
julia> foo(x::Int) = ("new", Base.invoke(foo, Tuple{Real}, x))
foo (generic function with 2 methods)
julia> foo(1)
("new", "original")
If you’re not specializing, but just overwriting the method, you can still call the old version by invoking it in the world age before your new version was defined:
You’re right.
From your answer, I realised that what I want is close to replacing the imported method.
According to the answers, it would potentially be harmful.
Then, what would be the best way of replacing imported methods? (If necessary)
EDIT: for example, if I want to preserve the name of imported method while modifying the imported method, what would be the best practice?
If you just want a function with the same name, but which is not a method of the original function, you just need to not import the other function into your namespace and instead refer to it explicitly, e.g. if you want to swap argument order or something:
Could you provide some context as to what you are trying to achieve?
I conjecture there may be a different design pattern that would serve you better than replacing a method in a package.
In my case, a package MyPkg exports a function my_func with method my_func(multicopter::Multicopter).
I would like to preserve the method my_func(multicopter::Multicopter) while it acts slightly differently.
For example, I import the method my_func(multicopter::Multicopter) and reuse it for custom multicopter models with additional features, e.g., fault models.
Have you considered defining a new Multicopter type for this? I.e.,
module Copters
# Hopefully there is an abstract type
abstract type AbstractHelicopter end
struct Multicopter <: AbstractHelicopter
[...]
end
my_func(m :: AbstractHelicopter) = [...]
end # module
using .Copters
struct FancyCopter <: AbstractHelicopter
[...]
end
function my_func(m :: FancyCopter)
Copters.my_func(m)
# do some FancyCopter specific extra stuff
end
BTW, to inherit other methods for Multicopter, how about making FancyCopter a sub-type of Multicopter and defining a specific method my_func(m::FancyCopter)?