How "abstract" modules structs in Elixir?

Hello everyone!

I’d like to know if its possible “abstract” (Inherit) modules in elixir, I know this one of the bases of OOP but I want to know if its possible make something like this on a Elixir way:

Suppose that a map in a game has many entities all contained in one list, the entity can be a player, a monster, a npc etc…

So in c# (for example) I create a base class called Entity that contains a constructor with id and name parameters, with this base class I can create a Player class (public class Player : Entity) that inherit the entity constructor (with this the fields id and name too!) an so one with the other types of entities

There is something like this on elixir? Or in the example of the game map I need to create a separate list to every kind of entity? and every module write the id and name and arent related each other?

Greetings!

The closest thing you will find in Elixir is probably Protocols. Protocols are the mechanism of polymorphism over data types in Elixir and allow you to define a set of functions that apply to many data types, and in particular structs. This is the facility used to implement the Enum functionality that works on lists, maps, and other collections.

In this case you would probably have an “Entity” module that defines a function, call it Entity.create, then when you are trying to construct a particular entity… say the Player you would include a call to Entity.create in the implementation of Player.create. The common function that would go in the Protocol of all modules would be the create function.

Having said that, you should spend some time rethinking your paradigms. What it seems you are trying to do is apply Object Oriented inheritance in a functional language. It’s certainly possible to make that happen, but can be the “wrong” choice. I’m not sure how an Entity-Component game engine might best fit in the Functional paradigm, but it sounds like a fun area to explore :slight_smile:

2 Likes

Another possible area of exploration, and something akin to protocol enforcement, is Behaviours. You can create a scheme where one module provides a set of generic behaviors and calls upon another module to provide specialization using behaviors to ensure that your second module implements the correct functions. This is done for OTP modules like GenServer so investigating the relationship between the generic GenServer module and a specific implementation of a GenServer might offer valuable insight.

1 Like

Thanks for answer!

Well exactly as you tell those are the best option I have figured out, also I found some project on elixir really helpfull, and here an example of behaviours:

I think this schema can work to my app, actually I’m making some tests with Elixir to handle a game protocol (just for practice the lang) but all the protocol on this game its fully OOP, I think I will have a lot of work translating it to a readable file like json ^^’

Again thanks for answer! Help me a lot :smiley:

Here’s another article that might help you organise your entity management a bit better. It is in Erlang but you should still get the gist of it: http://zxq9.com/archives/1311 (bear in mind that I’m not suggesting to model the entities as a process per entity, see: http://theerlangelist.com/article/spawn_or_not)

As it was suggested, you can try protocols, but there’s nothing wrong with some code duplication initially. Once you get a bit more familiar with how you want to organise your entities, you might see some patterns emerging.

I hope this helps!

1 Like

For LFE (Lisp Flavoured Erlang) I did an implementation of Lisp Machine flavors which is basically an OO package with all the “standard” stuff. It works as expected. Sort of. You could most likely do something similar for Elixir.

I agree with other posters and ask if this is really what you want as an OO package does not really fit on top of a functional language/system like Elixir (and Erlang and LFE). Classic style objects just don’t really fit.

1 Like

Thanks for your answers @lpedrosa and @rvirding!

The spawn example its amazing! It give me some guide to achieve what I want :smiley:

Sure, thats why I’m asking on the forum to get some ideas to replace this OO on my mind ^^

I think one correct way its to do actions based on methods partern matching, this can replace all OO stuff I think :slight_smile:

It may be worth your time to watch Skills Matter 2015-01-15: Functional programming design patterns with Scott Wlaschin (multiple times if necessary) to help with the “re-think”.

I believe ths common way to implement thimgs which in class-oriented programming would be solved with abstract base classes, would be to use a Protocol for the underlying (internal!) parts that will be different for each implementation, and a public API living in a separate module that wraps this, providing the common parts that will always be the same. This approach is relatively natural and very maintainable.

One example that comes to mind is Enum(the public API to work with enumerating collections) which wraps the Enumerableprotocol that you can implement for your own data type.

1 Like

Thats an amazing example :smiley: so many thanks!!

The code/method part is not a problem, my flavors do this as expected. No problems here.

No I think the fundamental issue when thinking in an OO style is to work out how to represent objects. “Classic” OO objects are shared mutable data structures for which there is really no natural way of representing in erlang/elixir. One way is to use a process which works but is “heavier” than OO objects. Another way is just local data which is nice and light but gives you a completely different way of working with them as they are not shared nor mutable.

2 Likes