# Extend methods from another module while calling the original method within the extended method

**URL:** <https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791>\
**Category:** New to Julia\
**Tags:** package\
**Created:** [June 12, 2021, 12:49pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791 "2021-06-12T12:49:39Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [June 12, 2021, 12:49pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/1 "2021-06-12T12:49:39Z")

</div>

Hi,

I wonder if it’s possible to extend a method from another module while calling the original method within the extended method.

For example,

```julia
function MyPkg.myfunc(x; t) # extended method
    2*MyPkg.myfunc(x; u=t) # original method's form: myfunc(x; u)
end

```

Of course, the above method does not work properly.

What should I do?

EDIT: I wanna preserve the name `myfunc` if possible.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 12, 2021, 7:09pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/2 "2021-06-12T19:09:17Z")

</div>

One option:

```julia
julia> module Foo
         myfunc(x) = println("Foo original");
         end
Main.Foo

julia> import .Foo.myfunc as foo_func

julia> foo_func(1)
Foo original

julia> myfunc(x) = println("Extended", foo_func(1))
myfunc (generic function with 1 method)

julia> myfunc(1)
Foo original
Extended

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 12, 2021, 7:16pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/3 "2021-06-12T19:16:32Z")

</div>

Whether this is a good idea is another matter.  
You are not really extending `myfunc`; you are replacing it.  
This might break things.

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [June 12, 2021, 9:28pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/4 "2021-06-12T21:28:09Z")

</div>

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
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:

```julia
julia> original_world = ccall(:jl_get_world_counter, UInt,())
0x00000000000073b5

julia> foo(x::Real) = ("new", Base.invoke_in_world(original_world, foo, x))
foo (generic function with 2 methods)

julia> foo(1.)
("new", "original")

```

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [June 13, 2021, 4:24am UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/5 "2021-06-13T04:24:46Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 13, 2021, 12:00pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/6 "2021-06-13T12:00:42Z")

</div>

I don’t know. Both seem to work. Is there a benefit to using the (more complicated) world age approach?

---

<div class="post-metadata">

**Author:** ![marius311](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius311/32/3953_2.png) [@marius311](https://discourse.julialang.org/u/marius311)\
**Post date:** [June 14, 2021, 1:12am UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/7 "2021-06-14T01:12:34Z")

</div>

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:

```julia
import OtherPackage
myfunc(x,y) = OtherPackage.myfunc(y,x)

```

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [June 14, 2021, 3:02am UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/8 "2021-06-14T03:02:26Z")

</div>

As reading all comments, the notions of function, namespace, and method becomes clear.  
Thanks a lot!

Actually, I intended to replace the existing method of the original function (so this does not fit in my case).

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 14, 2021, 3:32pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/9 "2021-06-14T15:32:27Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [June 15, 2021, 3:15am UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/10 "2021-06-15T03:15:53Z")

</div>

Sure 🙂

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.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 15, 2021, 10:40am UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/11 "2021-06-15T10:40:34Z")

</div>

Have you considered defining a new `Multicopter` type for this? I.e.,

```julia
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

```

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [June 15, 2021, 2:18pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/12 "2021-06-15T14:18:13Z")

</div>

IMO, it’s the best remedy so far.

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)`?

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [June 15, 2021, 7:23pm UTC](https://discourse.julialang.org/t/extend-methods-from-another-module-while-calling-the-original-method-within-the-extended-method/62791/13 "2021-06-15T19:23:53Z")

</div>

I assumed that Multicopter was a concrete type. Otherwise, yes.
