# Is Julia's way of OOP superior to C++/Python? Why Julia doesn't use class-based OOP?

**URL:** <https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058>\
**Category:** Internals & Design\
**Created:** [December 18, 2020, 4:32pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058 "2020-12-18T16:32:10Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![StatisticalMouse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/statisticalmouse/32/43370_2.png) [@StatisticalMouse](https://discourse.julialang.org/u/StatisticalMouse)\
**Post date:** [December 21, 2020, 3:57pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/22 "2020-12-21T15:57:09Z")

</div>

Would a tail-recursive function like they write in Elixir/Erlang be efficient in Julia?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [December 21, 2020, 4:03pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/23 "2020-12-21T16:03:24Z")

</div>

Julia doesn’t have tail call elimination so if you recurse too far you will overflow the stack.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 21, 2020, 4:41pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/24 "2020-12-21T16:41:13Z")

</div>

Despite the fancy name, the expression problem is _definitely_ a stumbling block you’ve encountered many, many times in object-oriented programming, wether you knew what it was or not. From the OOP side (as opposed to the functional language perspective, where it is also a problem but looks quite different), it is simply the problem of trying to add a new operation to existing types. For what it’s worth, I go through this in depth in the video I linked above, but some people prefer written explanations. The core problem with class-based OOP is that methods live _inside_ of classes and everyone has to agree on what methods make sense to add to each class. You may think, “What is the problem? I have added methods to classes all the time?” In your own code that you fully control, sure, if you want a new method, just open up the class definition and add the method. The problem occurs when, as happens in the real world, there are many people sharing and reusing code. Which, you will note, is one of the main problems that OOP is intended to solve.

Suppose, for example, that I maintain a package like [ColorTypes](https://github.com/JuliaGraphics/ColorTypes.jl) but in a class-based language like Python or Java. Now further suppose that you want to treat each color object like a 3-vector (or however many channels it has) and do vector operations like addition, subtraction, and taking norms. You don’t even insist on using operators like `+` and `-`, you’ll happily write `color1.add(color2)`, `color1.sub(color2)` and `color.norm()`. You try to convince me to add these methods to the `Colorant` abstract base class. However, I don’t want to add these methods: I don’t want to take on more features to maintain and it’s not entirely clear to me if/how colors should behave like vectors because perceptual color space isn’t linear in terms of various representations like RGB, CMYK, HSV, Lab, XYZ, etc.

Given my refusal to add methods to ColorTypes, what can you do? Traditional OOP would tell you to define your own subclasses. Problem solved! Right? Well, let’s think it through. The implementation is not as simple as it sounds. You want to add methods to `Colorant` so that all the color types inherit the new methods you add and any generic operations you define work across all color types. So you subclass `VectorColorant <: Colorant`. But now how do you get all the corresponding vector versions of specific concrete subtypes like `RGB`, `HSV`, `CMYK`, etc.? You have to define your own parallel type hierarchy that mirrors the one in `ColorTypes`. If your language supports multiple inheritance (Java does not, Python does), you can define `VectorRGB <: (VectorColorant, RGB)`, but you have to do that for every possible subclass — even ones defined outside of `ColorTypes`. This isn’t great: the number of definitions you have to write scales with the number of concrete subtypes, but at least each definition is trivial.

If your language does not support multiple inheritance, then you’re pretty much stuck: you have to copy the definition of each subtype but inheriting from the `Vector`-prefixed variant of what the original type inherited from. At this point, you’ve copied the entire class hierarchy aside from the topmost abstract base class, which probably doesn’t have much in it anyway, so you might as well just make your own copy of the whole thing into your own separate `VectorColorTypes` package. You also fix a few annoyances with the original code while you’re at it. After a while the upstream `ColorTypes` package makes a few changes that you haven’t kept up with, and the `ColorTypes` and `VectorColorTypes` packages start to diverge. They’re still similar, but unless you both try really hard to keep them in sync, they gradually become more and more incompatible. OOPs! 😬

That’s not even the extent of the problems. Suppose you’re lucky enough to be in a language that supports multiple inheritance and you created a mirror hierarchy of trivial `Vector`-prefixed types without completely parting ways with the original `ColorTypes` package. Now you encounter some really neat `palette` method that someone wrote using `ColorTypes` that takes a single `RGB` value and produces an entire palette of harmonious colors based on it. But you want to use it with your `VectorRGB` type. You can’t use it directly, however, since the methods are defined specifically for the `RGB` type. Even though `VectorRGB` has the exact same structure as `RGB` and even supports all the same methods that do all the same things (remember, I only wanted to _add_ methods, not change the existing stuff), they are different types and not interchangeable: if some method returns `RGB` values, you cannot apply methods for `VectorRGB` objects to them. You have three options:

1. You can petition the author of the code to change it to handle `VectorRGB` as well as `RGB`; they many not want to do this, since it’s an unnecessary complication.

2. You can create a shim method for `VectorRGB` that converts the `VectorRGB` value to `RGB`, calls `palette` on it and then converts the returned colors back to `VectorRGB`. This works, but you have to do it for every function like `palette`.

3. You can copy the code and duplicated it for the `VectorRGB` type and part ways with the original author.

None of these is that bad, but you have to do this for every bit of `ColorTypes` functionality that you might want to use. It’s also funny how OOP, which is supposed to be this great enabler of code reuse and sharing, keeps pushing us towards just making our own copy of someone else’s code and modifying it 🤔.

The `palette` method is actually quite simple, so adding support for `VectorColorant` subtypes isn’t that complicated. In more complex situations where color types are consumed or constructed, adding support for different subtypes leads to a proliferation of complex OOP patterns in real world code bases, like the [visitor pattern](https://en.wikipedia.org/wiki/Visitor_pattern), the [abstract factory pattern](https://en.wikipedia.org/wiki/Abstract_factory_pattern), the [factory method pattern](https://en.wikipedia.org/wiki/Factory_method_pattern), the [prototype pattern](https://en.wikipedia.org/wiki/Prototype_pattern), etc.

How does all of this work out in Julia with multiple dispatch? All you have to do is define methods like this in your own code:

```julia
add(c1::RGB, c2::RGB) = RGB(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b)
norm(c::RGB) = norm((c.r, c.g, c.b))

```

That’s it. You don’t have to convince anyone of anything. You don’t have to copy their code. You can add methods at whatever level of the abstraction hierarchy is appropriate. It doesn’t even matter if other people want to use the same names for methods because if you define an `add` function in your code and they define a different `add` function in their code, these are separate function objects in different namespaces and there’s no issue at all. In OOP, the namespace of methods is global and shared, so method name collisions are a problem. The key reason all this is better with multiple dispatch is that, unlike OOP where methods are defined inside of classes, methods belong to generic functions and are defined outside of the types they apply to — potentially not even in the same code base. Each user of a type can add methods as they please, which other users can reuse or ignore as they prefer.

So even if you never realized you encountered the expression problem because you didn’t have a name for it, you almost certainly have. That time you wanted to just add one teensy tiny method to someone else’s class but couldn’t. That was the expression problem. That time you discovered that your favorite OOP language’s ecosystem has two or more non-interoperable packages for some subject and you need some features from both of them but can’t use them together. If not for the expression problem, they could share a core set of simple types while extending them with different methods on top of that shared core. That time you were tearing your hair out trying to understand what the [`SimpleBeanFactoryAwareAspectInstanceFactory`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/aop/config/SimpleBeanFactoryAwareAspectInstanceFactory.html) class is and how the heck you’re supposed to use it. That was also the expression problem: if people weren’t forced to subclass just to add a few methods, they could just share concrete types instead of needing so many layers of abstraction. Despite seeming so different, these are all manifestations of the same core problem in OOP languages, a problem which multiple dispatch solves simply and elegantly, thereby eliminating all these issues at once. The effectiveness of this solution is borne out by the unusually high degree of code reuse and sharing we actually see in the Julia ecosystem.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 21, 2020, 4:47pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/25 "2020-12-21T16:47:22Z")

</div>

Lisp is the original functional language and allows both mutation and rebinding of variables. Lisp and Julia are both functional languages, just not _purely_ functional. The criterion for a functional programming language is good support for functions as first-class objects — you need to be able to pass them as arguments and return them from functions. That allows patterns like `map`, `filter`, etc. Some would also require support for lexical closures, which Julia also has.

---

<div class="post-metadata">

**Author:** ![StatisticalMouse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/statisticalmouse/32/43370_2.png) [@StatisticalMouse](https://discourse.julialang.org/u/StatisticalMouse)\
**Post date:** [December 21, 2020, 5:08pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/26 "2020-12-21T17:08:05Z")

</div>

This wikipedia page is a good illustration of how hard it is for a language to add multiple dispatch afterwards. I have to say I’ve seen some of those examples in real life.

> **[Multiple dispatch](https://en.wikipedia.org/wiki/Multiple_dispatch)**
>
> Multiple dispatch or multimethods is a feature of some programming languages in which a function or method can be dynamically dispatched based on the run-time (dynamic) type or, in the more general case, some other attribute of more than one of its arguments. This is a generalization of single-dispatch polymorphism where a function or method call is dynamically dispatched based on the derived type of the object on which the method has been called. Multiple dispatch routes the dynamic dispatch De...

---

<div class="post-metadata">

**Author:** ![vedasulo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vedasulo/32/20324_2.png) [@vedasulo](https://discourse.julialang.org/u/vedasulo)\
**Post date:** [December 21, 2020, 5:11pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/27 "2020-12-21T17:11:08Z")

</div>

What if Julia would officially support `Multiple dispatch` way and `OOP` way officially?  
Both pros and cons would be solved… 🙂

(Although I found power of `multiple dispatch` reading materials and easier to read write and collaborate but … )

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 21, 2020, 5:13pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/28 "2020-12-21T17:13:40Z")

</div>

OOP is just single dispatch. Just dispatch on the first argument. Done.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 21, 2020, 5:14pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/29 "2020-12-21T17:14:01Z")

</div>

What benefits does the OOP offer that multiple dispatch doesn’t already solve?

---

<div class="post-metadata">

**Author:** ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)\
**Post date:** [December 21, 2020, 5:19pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/30 "2020-12-21T17:19:26Z")

</div>

OOP from my point of view means that you can add properties to classes and inherit them… But you can do this with Julia already…

---

<div class="post-metadata">

**Author:** ![vedasulo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vedasulo/32/20324_2.png) [@vedasulo](https://discourse.julialang.org/u/vedasulo)\
**Post date:** [December 21, 2020, 5:24pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/31 "2020-12-21T17:24:56Z")

</div>

I have nothing problem with it 🙂 .

I’ve one silly problem that i am looking for , like in classes we use like `class.` and hitting `tab` gives all `methods` interactively but in Multiple dispatch way.  
I’ve to use a function which prints all methods at once and not interactive. As we have in julia,  
`methods(...)` I am thinking a way to get interactively those methods like `auto completer` .  
This is [Is there Way to know methods/functions of classes(modules/functions) - #5 by vedasulo](https://discourse.julialang.org/t/is-there-way-to-know-methods-functions-of-classes-modules-functions/51944/5) and I hope that alot of innovation have done, this would come in future 🙂 .

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 21, 2020, 5:43pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/32 "2020-12-21T17:43:10Z")

</div>

> [@vedasulo](#):
>
> I am thinking a way to get interactively those methods like `auto completer` .

> <https://github.com/JuliaLang/julia/pull/38791>
>
> A number of calls to change the language have been justified in part by argument…s for better tab completion. It seems time to separate these issues by improving discoverability in a way that integrates with multiple dispatch. With this PR, \`?(x, y)TAB\` completes methods that can be called with \`(x, y)\`, and \`?(x, yTAB\` (without the closing \`)\`) completes methods called with \`(x, y, ...)\`. There is also limited module-scoping available (only one layer deep).
> 
> An alternative to \`?\` would be to have the cursor positioned where the function name should be supplied.
> 
> I'm happy to discuss changes to this, but depending on whether a couple of other deadlines evaporate I might not have time to make any substantive changes here for a while...so let me say at the outset that I'd be just fine with someone taking this over if desired. Or, it can sit until I get time.
> 
> Demos:
> \`\`\`julia
> julia\> InteractiveUtils.?("hello")\[TAB\]
> apropos(string) in REPL at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/REPL/src/docview.jl:727
> clipboard(x) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/clipboard.jl:60
> code\_llvm(f) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/codeview.jl:178
> code\_native(f) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/codeview.jl:199
> edit(path::AbstractString) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:195
> edit(f) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:223
> eval(x) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/InteractiveUtils.jl:3
> include(x) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/InteractiveUtils.jl:3
> less(file::AbstractString) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:256
> less(f) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:264
> report\_bug(kind) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/InteractiveUtils.jl:385
> separate\_kwargs(args...; kwargs...) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/macros.jl:7
> 
> julia\> InteractiveUtils.?("hello")\[SHIFT-TAB\] # this excludes duck-typed methods
> edit(path::AbstractString) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:195
> less(file::AbstractString) in InteractiveUtils at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/InteractiveUtils/src/editless.jl:256
> 
> julia\> ?(\[1 2; 3 4\], 1, 1)\[SHIFT-TAB\]
> LinRange(start, stop, len::Integer) in Base at range.jl:427
> StepRangeLen(ref::R, step::S, len::Integer) where {R, S} in Base at range.jl:366
> broadcast(f, x::Number...) in Base.Broadcast at broadcast.jl:824
> broadcast(f, avs::Union{Number, LinearAlgebra.Adjoint{T, var"#s828"} where var"#s828"\<:(AbstractVector{T} where T) where T}...) in LinearAlgebra at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/adjtrans.jl:281
> broadcast(f, tvs::Union{Number, LinearAlgebra.Transpose{T, var"#s828"} where var"#s828"\<:(AbstractVector{T} where T) where T}...) in LinearAlgebra at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/adjtrans.jl:282
> broadcast(f::Tf, As...) where Tf in Base.Broadcast at broadcast.jl:821
> broadcast!(f::Tf, dest, As::Vararg{Any, N}) where {Tf, N} in Base.Broadcast at broadcast.jl:860
> checkbounds(A::AbstractArray, I...) in Base at abstractarray.jl:608
> circshift!(dest::AbstractArray, src, shiftamt) in Base at multidimensional.jl:1116
> clamp(x::X, lo::L, hi::H) where {X, L, H} in Base.Math at math.jl:65
> clamp!(x::AbstractArray, lo, hi) in Base.Math at math.jl:93
> copyto!(dest::AbstractArray, dstart::Integer, src) in Base at abstractarray.jl:846
> error(s::Vararg{Any, N}) where N in Base at error.jl:40
> fill(v, dims::Union{Integer, AbstractUnitRange}...) in Base at array.jl:449
> get(A::AbstractArray, i::Integer, default) in Base at abstractarray.jl:1411
> getindex(A::Array, i1::Int64, i2::Int64, I::Int64...) in Base at array.jl:788
> getindex(A::Array, i1::Integer, I::Integer...) in Base at abstractarray.jl:1167
> getindex(A::Array, i1::Union{Integer, CartesianIndex}, I::Union{Integer, CartesianIndex}...) in Base at multidimensional.jl:637
> getindex(A::AbstractArray, I...) in Base at abstractarray.jl:1161
> isassigned(a::Array, i::Int64...) in Base at array.jl:201
> isassigned(a::AbstractArray, i::Integer...) in Base at abstractarray.jl:505
> map(f, x::Number, ys::Number...) in Base at number.jl:238
> mapreduce(f, op, a::Number) in Base at reduce.jl:419
> rand(X, d::Integer, dims::Integer...) in Random at /home/tim/src/julia-master/usr/share/julia/stdlib/v1.7/Random/src/Random.jl:283
> repeat(A::AbstractArray, counts...) in Base at abstractarraymath.jl:223
> reshape(parent::AbstractArray, dims::Int64...) in Base at reshapedarray.jl:116
> reshape(parent::AbstractArray, dims::Union{Int64, AbstractUnitRange}...) in Base at reshapedarray.jl:110
> reshape(parent::AbstractArray, dims::Union{Colon, Int64}...) in Base at reshapedarray.jl:117
> selectdim(A::AbstractArray, d::Integer, i) in Base at abstractarraymath.jl:122
> setindex!(A::Array{T, N} where N, x, i1::Int64) where T in Base at array.jl:825
> setindex!(A::Array, v, i1::Union{Integer, CartesianIndex}, I::Union{Integer, CartesianIndex}...) in Base at multidimensional.jl:639
> setindex!(A::AbstractArray, v, I...) in Base at abstractarray.jl:1258
> similar(a::AbstractArray{T, N} where N, dims::Union{Integer, AbstractUnitRange}...) where T in Base at abstractarray.jl:735
> view(A::AbstractArray, I::Vararg{Any, N}) where N in Base at subarray.jl:164
> \`\`\`
> 
> Closes #30052
> xref #38704
> xref #37993

---

<div class="post-metadata">

**Author:** ![vedasulo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vedasulo/32/20324_2.png) [@vedasulo](https://discourse.julialang.org/u/vedasulo)\
**Post date:** [December 21, 2020, 5:48pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/33 "2020-12-21T17:48:45Z")

</div>

Exactly this I was talking 🙂 .  
It seems these have been merged. I hope i will see this using some extensions in ide’s .

_When could i see it in action? 🙂_

```julia
a = [1]

```

giving `a` all autocompletion interactively or tab . and it was added 12 days ago:) , I am waiting.

Thanks…

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 21, 2020, 5:57pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/34 "2020-12-21T17:57:50Z")

</div>

> [@vedasulo](#):
>
> It seems these have been merged.

No, it’s not merged yet — that’s why the PR is listed as “open”. Even when it is merged, you won’t see it until Julia 1.7.

---

<div class="post-metadata">

**Author:** ![vedasulo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vedasulo/32/20324_2.png) [@vedasulo](https://discourse.julialang.org/u/vedasulo)\
**Post date:** [December 21, 2020, 6:07pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/35 "2020-12-21T18:07:49Z")

</div>

🙂 I hope will see soon.  
Thank you @stevengj 🙂

---

<div class="post-metadata">

**Author:** ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)\
**Post date:** [December 21, 2020, 6:16pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/36 "2020-12-21T18:16:26Z")

</div>

Two words: Type Piracy.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [December 21, 2020, 6:18pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/37 "2020-12-21T18:18:12Z")

</div>

Those are indeed two words.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [December 21, 2020, 6:21pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/38 "2020-12-21T18:21:30Z")

</div>

> [@lobingera](#):
>
> Two words: Type Piracy.

While it’s often useful to be as terse as possible when making a point, I think using just ‘two words’ didn’t convey what you wanted it to. Could you explain why you think those two words are relevant?

---

<div class="post-metadata">

**Author:** ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)\
**Post date:** [December 21, 2020, 6:26pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/39 "2020-12-21T18:26:23Z")

</div>

That example was not type piracy. It defined a new function which would be scoped to that module. For example `SomeModule.somefunction()` and `OtherModule.somefunction()` are two different functions which happen to share the same name, not type piracy.

---

<div class="post-metadata">

**Author:** ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)\
**Post date:** [December 21, 2020, 6:58pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/40 "2020-12-21T18:58:12Z")

</div>

> [@Tamas\_Papp](#):
>
> such as reading the manual, or [a book like this](https://www.packtpub.com/product/hands-on-design-patterns-and-best-practices-with-julia/9781838648817)). This may not exist in unpaid form

Ah, just realised that the eBook is on sale for 5 Euro 🙈 thanks for mentioning it!

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [December 21, 2020, 7:31pm UTC](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058/41 "2020-12-21T19:31:41Z")

</div>

> [@StefanKarpinski](#):
>
> How does all of this work out in Julia with multiple dispatch? All you have to do is define methods like this in your own code:
> 
> ```julia
> add(c1::RGB, c2::RGB) = RGB(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b)
> norm(c::RGB) = norm((c.r, c.g, c.b))
> 
> ```

Won’t it look basically the same in languages such as python? As I understand, the power of multiple dispatch comes not from just the ability to define new functions operating on existing types - this is possible in the majority of popular languages. In fact, your example doesn’t need dispatch at all, if it doesn’t do piracy:

```python
def add(c1, c2):
    return RGB(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b)

def norm(c):
    return np.norm([c.r, c.g, c.b])

```

[Previous page](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058.md?page=1)

[Next page](https://discourse.julialang.org/t/is-julias-way-of-oop-superior-to-c-python-why-julia-doesnt-use-class-based-oop/52058.md?page=3)
