66

I'm working on Juno with Julia.

I don't know if Julia supports OOP or not.

For example, is there something like class or struct of c++?

How to declare it with members such as a data or a function?

Ravindra S
  • 6,302
  • 12
  • 70
  • 108
Yves
  • 11,597
  • 17
  • 83
  • 180
  • 13
    When I Google `Does Julia support OOP` I get plenty of related articles. Are they not helpful? Really? – Pekka Nov 17 '15 at 11:27
  • 13
    This question is the first result that appears when I look that on google ;). In any case it's quite difficult when you pass from python or c++ language to get that into your mind and to get it working. In my own experience =) – silgon May 30 '16 at 15:06

8 Answers8

64

When in doubt, read the documentation...

https://docs.julialang.org/en/v1/manual/types/#Composite-Types-1

Long story short:

struct MyType
    a::Int64
    b::Float64
end

x = MyType(3, 4)

x.a

EDIT: Methods are defined outside the type definition, e.g.

function double(x::MyType)
    x.a *= 2
end

Methods do not live inside the type, as they would do in C++ or Python, for example. This allows one of the key features of Julia, multiple dispatch, to work also with user-defined types, which are on exactly the same level as system-defined types.

Shlomi Fish
  • 4,380
  • 3
  • 23
  • 27
David P. Sanders
  • 5,210
  • 1
  • 23
  • 23
  • 1
    this may seem a bit pedantic (i am not trying to!), in python your function `double()` will just be a function, not a method. details: https://stackoverflow.com/questions/20981789/difference-between-methods-and-functions – stucash Nov 14 '17 at 22:04
  • 3
    The point is that in Python you would often define x.double(), i.e. a double method of the object. – David P. Sanders Nov 15 '17 at 15:10
  • 1
    Hmm, so no encapsulation, nor public/protected access. Therefore can't be OOP, interesting. (Side note - that is a partial problem with the partial way Python did it as well, but at least Python's poor default performance kept it away from large systems, with Julia it worries me) – SeventyFive Aug 23 '18 at 11:50
  • Methods/functions are black-boxes so they are encapsulated. Public/protected can be done on the module level by appending _, __, to names, and not exporting methods, or using closures. – aoeu256 Sep 13 '19 at 19:11
  • Is your comment "Methods are defined outside the type definition" intended literally? as in outside of ``struct ... end`` or do you mean a metaphorical 'outside'? Because it is possible to define "inner methods" inside of ``struct ... end`` – PatrickT Apr 27 '21 at 06:52
55

Julia is not object-oriented in the full sense because you cannot attach methods to Julia's objects ("types"). The types do seem very similar to objects though. However, since they do not have their own associated methods and there is no inheritance the objects themselves don't do the acting. Instead you have functions which act on the objects.

The difference is ball.checkCollision() vs checkCollision(ball,Walls). In reality it's not that big of a deal. You can make something like inheritance by having a type have a field of another type, and multiple dispatch lets you write functions which do different things based on the objects you give them, which can be almost like object methods. The real difference is where you save the function and types in a file. So you can do a kind of quasi-objected-oriented style in Julia, but it's still distinctly different than OOP languages.

Chris Rackauckas
  • 18,645
  • 3
  • 50
  • 81
  • 1
    The big deal between ball.check() and check(ball), is encapsulation, and public/protected etc access. I elaborated in another comment. (And "access by convention" never sticks when an urgent bug comes, but explicitly changing an access modifier without design justification is something I almost never seen people do) – SeventyFive Aug 23 '18 at 11:55
  • 5
    Yes, and the fact that you can extend methods from other packages has become a major feature in Julia which allows very nifty tricks. DiffEq/JuMP's confederated package APIs utilize it. Putting dual numbers into differential equations and optimizers for multi-level optimization is using it. It's a really nice advantage over OOP that took a few years to develop a distinctly useful style. Now it's difficult to go back to OOP given the loss of functionality. – Chris Rackauckas Aug 23 '18 at 13:38
  • 1
    Chris, you are pulling along in the direction of a language argument, I'll go with you but just for a bit as I do not think it's a great Path: Ok, so in practice you are talking about multiple inheritance combined with unencapsulated methods dogma. You could use virtual inheritance and "friends" to do it in OOP langs easily, but why do people choose to avoid it? Because this dogma takes us back to the days of lookup tables in C. It's fun for a script, and a disaster for even a middling 1M lines of code system. It's history the same way overwriting code memory is, it was unmaintainable. – SeventyFive Aug 25 '18 at 00:08
  • 5
    The multiple dispatch mechanism and designs around have been found to be maintainable in my and other's experience. I gave a few examples of some "just works" behavior in Julia which accounts for this, and there's many more, for example SymEngine.jl types acting as numbers and uncertainty quantification in larger codes via Measurements overloads. It does have both advantages and disadvantages, and whether such the engineering tradeoffs are good/bad can be discussed at length elsewhere. We can chat privately about our opinions but I am not sure this is relevant to the answer anymore. – Chris Rackauckas Aug 25 '18 at 00:45
  • 3
    Julia has multiple *dispatch*, not multiple inheritance. As for breaking encapsulation, pretty much every dynamically typed OOP language lets you do this, it is entirely orthogonal to multiple dispatch. However, multiple dispatch lets you avoid the horrible visitor pattern boilerplate that you would need to represent any nontrivial math in a class-based OOP setting without multimethods. – saolof Jan 19 '19 at 00:42
  • `Class.methods()` is a more natural fit for OOP anyways – Kermit Aug 05 '21 at 14:47
18

I would like to mention this worthfull conversation within Julia users group Julia and Object-Oriented Programming.
For me Julia is not like a conventional OO language, and I always like to think of Julia, as more a Method Oriented language that an Object Oriented one, that is because if you try to create an structure of encapsulated data and functionality in Julia, soon you will get yourself into trouble.

Reza Afzalan
  • 5,646
  • 3
  • 26
  • 44
7

The answer is that Julia is closer to c rather than c++. Thus, OOP is limited in Julia having only c::struct rather than c++::class. Hence, it's just data encapsulation or data structure or customization of Types rather than true OOP objects, in the strict sense.

geekborj
  • 87
  • 1
  • 1
  • 2
    This is answer would be better if it includes some references in detail claiming the same as the answer. – Syakur Rahman Sep 01 '18 at 02:05
  • 2
    No Julia uses multimethods like Haskell or Lisp, rather than overloading based on the implicit object A, the functions are overloaded on all arguments at the same time. Its a generalization of OOP, and there should be a method of auto-completion like OOP. – aoeu256 Sep 13 '19 at 19:18
3

Yes. You just can't inherit from concrete "classes" with fields, only from abstract ones. This is because the memory layout of a concrete struct in Julia is part of its interface, and being able to subclass it by adding fields would break the Liskov substitution principle.

However, Functions with multiple dispatch are a strict generalization of methods with single dispatch and are strictly more polymorphic. You just have to define them outside of a class definition, because they can "belong" to multiple objects.

Traditional methods in an OO language are a special case of Julia functions where you only have dispatching based on the first argument.

saolof
  • 1,097
  • 1
  • 15
  • 12
  • 2
    Can you do autocompletion with multimethods? I remember in Haskell or maybe Prolog and Idris you could do combine hoogle and a thing called _ (holes) so _ a b :: Int would tell you all methods that take in a and b and return Int. – aoeu256 Sep 13 '19 at 19:17
2

I'm no expert on the language but my understanding is: Yes..and no.

It has the equivalent of classes and structs, however there are no methods on those objects other than a single constructor.

In mainstream object oriented languages, such as C++, Java, Python and Ruby, composite types also have named functions associated with them, and the combination is called an “object”. In purer object-oriented languages, such as Python and Ruby, all values are objects whether they are composites or not. In less pure object oriented languages, including C++ and Java, some values, such as integers and floating-point values, are not objects, while instances of user-defined composite types are true objects with associated methods. In Julia, all values are objects, but functions are not bundled with the objects they operate on. This is necessary since Julia chooses which method of a function to use by multiple dispatch, meaning that the types of all of a function’s arguments are considered when selecting a method, rather than just the first one (see Methods for more information on methods and dispatch). Thus, it would be inappropriate for functions to “belong” to only their first argument. Organizing methods into function objects rather than having named bags of methods “inside” each object ends up being a highly beneficial aspect of the language design.

Tim B
  • 40,716
  • 16
  • 83
  • 128
0

It would be nice if they thought of method grouping like C# Helper methods. I'm sick to my stomach because of the Julia language, though not as much as Python. Julia seems like a dirty, scruffy girl.

public static class StringHelpers
{
    public static char First(this string str)
    {
        return str[0];
    }
}

string thisMonth = "January";
var firstChar_0 = thisMonth.First(); // J
var firstChar_1 = StringHelpers.First(thisMonth); // J

Console.WriteLine(firstChar_0 == firstChar_1); // True
0

There are many macros that approximate object orientation (this is possible because of the cool metaprogramming features)

I recently converted to ReusePatterns.jl because this is the closest to idiomatic Julia and thus plays nice with the rest of Julia, but it does not support Multiple inheritance. (It also has a list of other similar packages)

For a long time I was using OOPMacro.jl, this works well but still feels a bit at odds with how Julia wants to work, which has caused some weirdness for me at times, hence I'm moving on.

AmanicA
  • 4,659
  • 1
  • 34
  • 49