Multiple dispatch basically is just a system where methods are registered with the types that are provided as arguments. For example, let us consider that the calculation of two things will yield the same result, but the steps to get there are semantically different. In this example, we will consider this with an example from a package I wrote. In this example, we have two types, the first is the OddFrame, which is just a data structure similar to a typical DataFrame, and then there is the FrameGroup. The FrameGroup is a collection of OddFrames. If we wanted to get the labels of the OddFrame, as an example, it would be quite different to getting the labels of the FrameGroup. If we just provide the types to the arguments in the same function definition, we can get the same functionality from the same call for two entirely different structures, e.g.
names(od::AbstractOddFrame) = od.labels
names(fg::OddFrameContainer) = [label for label in fg.labels]
These are abstract versions of the types, the types OddFrame and Framegroup are sub-types of AbstractOddFrame and OddFrameContainer reespectively.
Now if we were to call names() on one or the other, we get the same result, but the steps we took to get there were different. For the end user, they do not even realize things are different. It goes much further in Julia as it is used to extend functions, do indexing, iteration, and can actually allow you to do so much cool stuff with constructors. If you would like to see some rather advanced constructors, you can actually look at the source for those constructors here:
Comparing it to object-oriented programming, which perhaps you are more familiar with, these dispatch calls work to create the same methods while not making the methods children of any particular type.