3 ms·
It doesn't. Inheritance is about defining interfaces. It doesn't give you runtime swapability or anything like that; you need to wire that up yourself. For exa
by ndriscoll 2y ago
It doesn't. Inheritance is about defining interfaces. It doesn't give you runtime swapability or anything like that; you need to wire that up yourself.
For example, here[0] I have a concise way to define two logger implementations as functions. You could also do it by defining those two implementations as classes. In either case, the implementation is essentially provided by defining a constructor. In FP world, the constructor is the class.
Swapping is done elsewhere through some layer of indirection. So in OOP maybe you'd have a singleton class that hands out and can update the current logger. In FP, you might pass a `() => Logger` or `IO Logger` to your application, which does the same thing. You could define your FP "singleton" as
def managedLogger(init: Logger): (IO Logger, Logger => IO ()) = {
val ref = Ref.make(init)
(ref.get, ref.set)
}
Then you pass your getter to your main application, and your setter to whatever portion can do the setting (e.g. an HTTP handler). Your getter/setter might have more going on in practice (e.g. flushing and closing the old logger when swapping), but that's the basic skeleton. If you wanted, you could also put the two functions into a LoggerManager record type, and then it would be pretty much exactly the same as the OOP solution but without the incantations around classes and inheritance and "overriding" things.
[0] https://news.ycombinator.com/item?id=41904438 https://news.ycombinator.com/item?id=41904438