In F# you can define records with member functions, and you can also create classes.
type Album = {
Id: int
Name: string
DateReleased: DateTime
Genre: Genre }
with
member this.PrintMessage() =
printf "Hello from %s\n" this.Name
so used
let first =
{ Id = 1;
Name = "Hello World!"
Genre = KPop;
DateReleased = DateTime(1991, 8, 12) }
first.PrintMessage()
and with classes it could be something like this.
type Album(
Id: int,
Name: string,
DateReleased: DateTime,
Genre: Genre ) as me =
do
me.PrintMessage()
member this.PrintMessage() =
printf "Hello %s" Name
When it is convenient to use one or the other? Can Domain Modeling only be done with records?
Can a class be converted to a record and vice versa by some hidden FSharp Casting?
Domain modeling can be done with both records AND classes. I think when to use one or the other is primarily a matter of preference and environment. Personally I typically do not use classes, however I know some people who use them quite frequently. Classes rely more on mutation and are more performant at a cost of ease of use. Personally I feel as a general guidance that if you are going to write object oriented style then use classes and if you are writing functional style use records. Records pattern match and deconstruct easier. Part of this distinction is cultural, just because you can do a thing in a particular way doesn't mean other people will be able to understand you easily. Code is written to be read, both by yourself and others. When you pick records or classes it communicates intent about the style and usage of those types. Finally I don't know that a class can be converted to a record within F# and if it can I would actually still recommend against it. This is because using records as classes and classes as records clashes with the cultural norms around those constructs. I personally think your example member is fine for both records and classes. I normally like to use modules with the same name for functions associated with a given type because it can make it less confusing when the function happens to consume something other than the record type. However I don't think anyone well mannered would balk at either of your code examples there.
type Album(
Id: int,
Name: string,
DateReleased: string,
Genre: int ) as me =
let mutable genre = Genre
//readonly property
member val Id = Id
//autoproperty with get and set
member val Name = Name with get, set
member val DateReleased = DateReleased with get, set
//property with explicit get and set
member this.Genre
with get () = genre
and set (value) = genre <- value
see When should I use let, member val and member this.?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With