F# is a first-functional language but, being multi-paradigm, it can handle classes, objects, inheritance, methods, etc. Since many of my friends are used to languages like Java or C# (or even C++), the question of whether you can do object-orientation with F# arises frequently, so much so that I’m going to try and show you some examples on how to do it. I have to say right out of the bat that they are going to be (very) simplistic examples, but I hope they will give you a realistic idea of how to write O-O F# anyway. I’m going to use the typical scenario of a Vehicle class from which a Car class descends. For starters, let’s see how to define color as an enumeration (we do use enumerations, right?) and position as an immutable object (the specific coordinates (0.24,-78.5) do not change, if a vehicle moves its position changes obviously, but it does so by receiving new coordinates). The Java version:

Someone may say that longitude and latitude should have getters, but since a Position instance doesn’t change (hence the final in the field declarations), defining and using a getter seems excessive and I don’t want to make Java look longer than necessary. Now the F # version:

The enum syntax is different, but the equivalence is clear. Position does bring some new ideas: what we are seeing is a record declaration, a simple object type that only has properties, which are also immutable (like Java’s final fields), this could look like a very narrow case, but as F# favors using immutable elements, it happens much more frequently than in your average O-O code.

Now on for something with more meat to it -with apologies to my vegan friends :-) The Vehicle class, which is abstract, has a few fields, a constructor and a method. The Java version:

As is usually the case, the Color, Position, and Speed fields, together with its getter and setter declarations take up much of the space; the constructor initializes a couple of those fields via its respective setters, as recommended in Java; finally, the Accelerate method increases the speed and returns the new value, of course we could, we should, have much more logic there but that’s not the focus of this article. Now the F# version:

Right at the first line, it is kind of odd the usage of the AbstractClass attribute to signal that we are dealing with an abstract class (hey! No one said everything was going to be obvious around here :-) ), with that over let’s deal with more salient details:

  1. The parentheses just after the class name indicate that the default constructor has no arguments (aha, yes, those “()” are our Vehicle() constructor declaration ;-))
  2. Color, Position, and Speed are properties with invisible fields behind them, with automatically generated getters and setters, similar to those of the Java version
  3. That {length = 0.0; latitude = 0.0} code instantiates a Position object, in effect it is the equivalent of new Position (0, 0)
  4. The Accelerate method has one argument, no parentheses around it needed, no return keyword required either: the very last evaluated expression, in this case this.Speed, is returned
  5. Finally, there’s no need for any type declaration, all those Color, Position, float-> float, and the like in light grey, are visual hints created by the compiler, nothing that I had to type in.

All in all, we’re talking about 32 Java lines vs. 8 F# lines to express the exact same thing. A 75% savings of lines to read and understand is pretty good, isn’t it? :-)

We are almost done, Car is a class inherited from Vehicle that adds a field, immutable just to illustrate the way such thing are done, and a method. The Java version:

Brand is a property initialized inside the constructor that doesn’t change afterwards; the constructor receives two parameters: brand which is mapped to a local field and color which is mapped to an ancestor field via its setter; Finally, the PullHandBrake method slows down the car to 0 (I did say that this was going to be a simplistic example, right? :-)) using the ancestor’s methods and getters, nothing earth-shattering here. Now, the F # version:

Car descends from Vehicle, the syntax is obvious, but again we have some interesting details:

  1. The () after Vehicle signal which ancestor constructor will be called as part of a Car object instantiation, so it causes the same effect as a Java super() call
  2. The Car constructor itself takes two parameters, which are used in two different places: a) Inside the do statement, where the default constructor logic is placed; b) At the Brand property initialization Brand: string = brand, which by the way has no setter, making it immutable.
  3. The value returned by PullHandBrake is the same as in Java, but I like to think that there is less noise here :-)

Here we had only a 50% savings in code lines but still not that bad, eh?

I hope that these (very) simple examples made it clear that F# can be as O-O as Java or C#, but remember: it is a good idea to try to be functional first and only when it doesn’t come natural to go back to O-O, otherwise what would have been the point of moving to a functional language? Any comments?

Update 1: You can get the F# and Java code samples here.

Update 2: Join the functional movement!




(Functional) software developer, aspiring trail-runner/triathlete, math fan. Lives and loves in Ecuador, South America.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Visualize Journey of a Feature with Dependencies, Risks, and Stories

Platform for Game Developers to integrate with blockchain tech easily

Configuring KeePass to Start Automatically

HubSpot Chat widget integration!

Starting to understand Multitenancy


Join us | Tri Petch Internship program 2022

Single or Multi Page Web Apps: What to Choose for Web Development | Claritus Management Consulting

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Edgar Sánchez

Edgar Sánchez

(Functional) software developer, aspiring trail-runner/triathlete, math fan. Lives and loves in Ecuador, South America.

More from Medium

Collections and Generics

Importance of Unit and Integration Tests

Single Responsibility & Domain Design: Action and Agent

Git: Working In a Team