Mastering F# Classes
F# classes allows you to leverage the benefits of both functional and OOP paradigms in your code. In this article, we will delve into F# classes and explore their unique features, syntax, and best practices to help you master the art of OOP in F#.
Although the F# language is known for its concise and expressive syntax when it comes to functional programming, it also supports class and object concepts commonly found in object-oriented programming (OOP).
The term class refers to a type that represents an object that has properties, methods, and events. In an application, these models can be used to represent actions, processes, and conceptual entities.
F# classes provide a way to define objects with mutable state and behavior.
A class in F# is a blueprint for creating objects that encapsulate data and methods.
It follows the same basic principles of OOP, including encapsulation, inheritance, and polymorphism. However, unlike in some other object-oriented languages, classes in F# are immutable by default, meaning their properties cannot be changed once they are set.
Defining F# Classes
In F#, you can define a class using the type keyword, followed by the name of the class, optional type parameters, and a set of class members, such as properties, methods, and events.
A class type is defined using the following syntax:
// Class definition: type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] = [ class ] [ inherit base-type-name(base-constructor-args) ] [ let-bindings ] [ do-bindings ] member-list ... [ end ] // Mutually recursive class definitions: type [access-modifier] type-name1 ... and [access-modifier] type-name2 ... …
- The type-name of the class can be any valid identifier. A public access modifier is the default for this access type.
- The type-params are a set of optional generic type parameters that may be used.
- The parameter-list describes the parameters that are used in the constructor. The primary constructor has a public access modifier as its default.
- The identifier is used as part of the optional as keyword in order to give an explicit name to the instance variable, or self-identifier, which is then used to referred to as an instance of the type in the definition of the type.
- The inherit keyword is used for specifying the base class of a class that you are creating.
- The let bindings make it possible to declare fields and function values that are local to the class for use within the code.
- The do-bindings section contains the code that will be executed when the object is constructed.
- The Member-list in the class include constructors, instance methods, static methods, interface declarations, abstract bindings, properties, and events declarations in addition to the constructors.
- The keywords class and end are optional keywords that specify the start and end of the definition, respectively.
Constructor of a Class
Creating an instance of a class type is the function referred to as the constructor.
There is a little difference in how constructors work in F# compared to other .Net languages.
Class definitions describe the arguments of primary constructors as parameter lists.
Let and do are used as the body of the constructor.
Adding more constructors to your class is as simple as adding a member by using the new keyword:
new (argument-list) = constructor-body
A simple example of how this concept can be illustrated is as follows:
This program creates an object of the line class along with a constructor that calculates the length of the line during the creation of an object of the class:
And the output will be as follows:
Hello Jeff Bezos
In this example, we define a class called “Greetings” with a single constructor that takes a parameter “name“. We use the “as greet” syntax to create an alias for the instance of the class that will be created.
Inside the constructor, we assign the value of “name” to a mutable field “user” in the class. Then, we have a “do” block, which is automatically executed immediately after the object is created.
Inside the “do” block, we call the “MessagePrinting” method on the “greet” object, which is the alias we created for the instance of the “Greetings” class.
The “MessagePrinting” method is a member of the class, and it uses the “printf” function from the F# standard library to print a formatted string. The string “Hello %s ” is the format string, where “%s” is a placeholder for the value of the “user” field in the class.
Finally, we create a new instance of the “Greetings” class with the name “Jeff Bezos” and assign it to a variable “g”. This will trigger the constructor of the “Greetings” class, which will print the message “Hello Jeff Bezos” using the “MessagePrinting” method inside the “do” block.