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

I am thinking How can it applied in large projects or software development projects, if there is no oop.
I heard struct and things. But some answer told It is not oop.

What are advantage and disadvantage of using oop in julia way? Which one is more heavy?
I’m confused.

(Although i really didnt liked oop and feel easy in function, but industry wanted to learn oop)

6 Likes

Julia is a multi-paradigm language — and that includes support for object-oriented sorts of patterns. It has full support for objects and can fully support “object oriented programming” but it looks a bit different since data (the structs) and behavior (generic functions) are completely separated through multiple dispatch. That is, we don’t really support the typical “dot oriented programming” obj.method() idiom, so folks used to other OOP languages don’t see the OOP they’re used to here.

31 Likes

When people say OOP they typically mean classes under which data and “methods” are bundled together. However, for a new Julia user, I wouldn’t get too hung up on terms like “OOP” and other terms that try to put a language into some type of box. These terms can never give an accurate view of how the language will feel to you. It’s like trying to describe an intricate painting with a few words, quite pointless. Instead, just use the language for different problems and you will get a feel for how it works. After you have some experience, you’ll be in a much better position to evaluate it and compare to other langauges.

44 Likes

One stated reason for multiple dispatch instead of attaching methods to classes is that with the latter, there is often ambiguity about which class the method should be attached to if it operates on multiple objects. Multiple dispatch solves this by removing the strong coupling to the self/this object.

20 Likes

I believe the standard answer is that Julia is not an object oriented language but it does have multiple dispatch. The problems most people are trying to solve in Julia are better suited to a functional language than an object oriented language.

That said you can organize your code to look like a basic object oriented language, but you can’t easily do the inheritance tricks that a full OOP language can do.

Truthfully for me as someone who has been in Java software development for a long time I’ve rarely seen many of the “cool” OOP features used in production code. If you are lucky there is just some basic inheritance to help with code reuse, mostly it’s just single classes that do whatever they need to do.

12 Likes

This article might be helpful to you: The unreasonable effectiveness of the Julia programming language | Ars Technica

4 Likes

FWIW, just to demonstrate diversity that exists in the use of any language, I also have many years experience in Java development, but mine does not match yours as described in the quote. Different strokes… I expect the diversity of application of various features in Julia would also be wide.

6 Likes

Many people don’t like OOP programming, it’s is cloying and complicates things unnecessarily, that’s why they choose functional programming languages such as Julia.

4 Likes

In my experience, Julia is more flexible than many OOP languages, such as Java. Traits are one example of the added flexibility that can be achieved with a combination multiple dispatch and Julia’s type system.

9 Likes

From a syntactic point of view, the main difference is if the functions that act on objects are part of the object or not. In some cases one thing is more natural than the other, in other cases it is the contrary. For example:

julia> mutable struct Person
         name
         height
         position
       end

julia> me = Person("Leandro","1.80",0.)
Person("Leandro", "1.80", 0.0)

julia> function displace!(p,Δx)
         p.position = p.position + Δx
       end
displace! (generic function with 1 method)

julia> displace!(me,2.)
2.0

julia> me
Person("Leandro", "1.80", 2.0)

The name and height are properties of me, and that makes sense. The displace! function acts on the the person, changing its position. That also makes sense. In a typical OO syntax, one would call something like

me.displace(2.0)

which is somewhat odd, I think. However, in other cases the natural way of thinking would favor this construct. For example:

julia> function walks!(p,Δx)
         p.position = p.position + Δx
       end
walks! (generic function with 1 method)

julia> walks!(me,2.0)
4.0

julia> me
Person("Leandro", "1.80", 4.0)

The function does the same, but now walking seems to be naturally a property of the a person, thus it could sound natural to call:

me.walks(2.0)

as in typical OO syntax.

Thus, it is not about what you can do, but how natural things look like at the end. In some cases the OO syntax looks more natural, in other cases the functional syntax is more natural. In math, in general, functional forms are more natural, I think, but it might be more natural to write in OO style if you are dealing with buttons, icons, etc, but that still depends on what operation one is doing to the object.

One great thing about the multiple dispatch in Julia is the following. If now I define another struct:

mutable struct Car
   color
   position
end

which also has a position field. You can simply use the same function to displace this car. You do not need to define a new function for that. On the other side, in strict OO programming you would need to define an abstract class of things to avoid having to copy the function to every type of object.

29 Likes

As an experiment, try creating a reasonably complex mutable struct in Julia - this is the thing that mimics the data part of a Java class - and then think about how you would either subclass it in Java or create facade interfaces, whatever - in order to give different behavior to that class under different circumstances. Now, back in Julia, implement the same function multiple times with different variations on the arguments, just as you might do with different Java methods on various interfaces. As a coder, I think you will immediately recognize how simple and straightforward it is to provide context-based behavior to your “class” which is the Julia struct. You can even dynamically build new functions and methods in Julia and execute them. That alone blows away anything Java can do. Embrace the difference!

11 Likes
21 Likes

Following the advice of some other thread I started reading the thesis of Jeff Bezanson. It is an excellent text. And I think that section 3.3 on Dispatch systems will completely answer your question here.

8 Likes

Trying to respond to a number of reactions at once (which may fail :wink:). When I got taught OOP at university one of the main challenges (which was focused on explicitly in the lessons) was how to model your actual problem using the restricted set of concepts that OOP provides. What classes do you need? Which methods should those classes have? Which fields? Should there be superclasses to group common data and/or behaviour? Etc. Once you get comfortable using OOP I don’t really find it too difficult or unnatural to use. Plus, a large number of often-used frameworks and languages are based on OOP so it’s a useful skill to have, as the general software world is very much object-oriented. It’s no wonder that even fairly new languages that have become mainstream, like Swift and Typescript still provide classical OOP features. Interestingly, Rust seems to have diverged by using trait objects instead of inheritance.

It can obviously make sense for certain sub-domains, like technical computing, to be based on a different paradigm, but I feel that discussions of Julia’s strengths often are too much focused on the promotion of multiple dispatch. Yes, it’s more powerful than single dispatch like in traditional OOP. But I don’t consider OOP actually that limited. So multiple dispatch doesn’t immediately provide a clear benefit for me, as it is a trade-off of more complexity and effort to apply, versus being able to leverage existing OOP skills/experience directly in Julia.

Plus, ironically the added flexibility Julia provides in how to model a problem doesn’t make it easier to use, as it will take quite some experience before you can use all that power effectively. How to apply multiple dispatch, taking advantage of the typing system, when to use traits (and through which package), when to use composition versus method forwarding (for simulating OO when needed, or should you simply use Classes.jl), etc. I’ve noticed quite a few posts on the forum here asking how to implement a certain tasks and then often see various answers with completely different (and incompatible) approaches. The variations then go beyond the usual choice in what algorithms and data structures to use (those suddenly appear mundane), as Julia adds a layer on top of those choices.

Even though I studied computer science most of the formal knowledge I got there has been long out of use, as you simply don’t need much of it with languages like C++ or Python, or OOP in general. Therefore the previous paragraphs summarizes the main type of knowledge I’m looking for in further learning Julia. Given a real-world problem/task of a realistic size how do you implement that in Julia, and why using those particular choices? So start from a concrete problem and then show how to use Julia’s power, instead of starting from a formal description of its features and then leaving the actual uses open.

5 Likes

Not really — since you don’t have a solution to eg the expression problem, you run into difficulties all the time. You may, of course, put up with them, like having a pebble in your shoe, but that does not make them go away.

This argument applies to almost all nontrivial areas of knowledge. Eg by the same token, you could argue that calculus does not make things easier, since you have to learn it first. Ironically.

Just look at any of the widely used Julia libraries.

17 Likes

Everything is relative. I’ve never heard of the expression problem, probably did run into it (as you claim you do all the time), but apparently it’s not really an issue in practice. And learning a new language or even switching the majority of your work over to it is always a trade-off between (perceived) benefit versus costs. It might very well be that Julia makes some things much easier, but that doesn’t necessarily imply it’s a good investment of time and effort overall (or in a particular case). There’s a large and diverse software world out there that does not use Julia and that’s not going to change anytime soon.

Which explains exactly nothing on why particular choices were made, or what alternatives could have been chosen.

3 Likes

https://wiki.c2.com/?BlubParadox

In case these choices are not accidental or trivial, usually you can track down the history using git (look at the source using “blame”, find the PR, read the discussion).

That said, what you are asking for is essentially a one-on-one tutorial into idiomatic Julia usage with the twist that you are not interested in making the initial investment (such as reading the manual, or a book like this). This may not exist in unpaid form — YMMV.

7 Likes

If you take a look at some of Uncle Bob Martin’s videos about clean code and programming languages he explains how the single most important aspect of OOP is polymorphism. Julia just chose to use it in the form of multiple dispatch. Inheritance and encapsulation can somehow be emulated, but that’s not the point. Encapsulation and inheritance come in OOP with their own limitations and dangers, and this is why we have interfaces and design patterns.

OOP is restrictive, and it’s more restrictive through the endless guidelines and design patterns that try to instruct the user to be careful, otherwise their library will end up as spagetti code and their dream of maintaining and extending the code will shatter.

Julia’s approach is a bit more liberating from this point of view, as the user doesn’t waste time figuring out if a new method can be added to one class or another, when, in reality it belongs to both with the same weight. This is a very useful approach for numeric libraries where operators like sum can’t be attached to one object more than to the other. (look how Python does away with this:).

Depending on application, one might favor one paradigm or another. Classical OOP make sense for example if one develops a GUI, where the inheritance hierarchy is top down, tree-like. But this doesn’t mean that every library should use this style. It’s just about the right tool for the job.

Heck, other people might simply like OOP just because of namespacing.(although you can’t “TAB” your way through everything).
That’s my 2c.

10 Likes

Didn’t know about that one either :wink: But I’m fully aware that Julia is more powerful and not just “merely a weird language […] about equivalent in power to Blub, but with all this other hairy stuff thrown in”. I’m just having a hard time making a step up the ladder.

Thanks for the book link, wasn’t aware of that one. It looks like it’s exactly what I need, so I just ordered and downloaded it (lots of their books apparently are currently in discount, for only 5 pounds).

7 Likes

I’d say Julia is not really a functional language as you can mutate variables.

Not that I mind that… I took a brief look at some Erlang tutorial, and it allows a variable to be assigned only once. I’d rather not start using Erlang.

1 Like