When to use an Object with a Apply Method
If its a pure function and thus doesn't require a class instance we can put it on an object. Additionally if its sufficiently complicated and decomposable that its functionality is implemented in several helper functions.
By naming it apply
, we indicate its the main function in the group of functions - and now we can invoke the object directly.
For example, a ComputeOptimalBinPacking
object/function was named after its main purpose. Thus using apply
has the nice effect that you can use it directly ComputeOptimalBinPacking(...)
whilst still being able to see the helper functions ComputeOptimalBinPacking.rotateBin(...)
.
It didn't really make sense to have ComputeOptimalBinPacking.actuallyComputeTheBinPacking(...)
exposed to callers (it makes it difficult to see which one they should use).
The only reason to use a case class would have been to curry multiple functions at the same time; and we are confident that the programmer will invoke multiple functions at the same time with the same curried parameters (e.g. it's pointless if the programmer only uses a single function and then discards the instance). For example, if we didn't want a facade across all of the helper functions:
case class ComputeOptimalBinPacking(generalWaste: List[GarbageCan], recycling: List[GarbageCan]) {
def compressedSquareBin(maximumWeightInKilograms: Int) = ???
def roundBin(diameterInMeters: Double) = ???
}
val packMyBins = ComputeOptimalBinPacking(wasteBins, recyclingBins)
packMyBins.compressedSquareBin(100)
packMyBins.compressedSquareBin(200)
packMyBins.doSomethingElse(0.8)
Instead of:
object ComputeOptimalBinPacking {
def compressedSquareBin(generalWaste: List[GarbageCan], recycling: List[GarbageCan], maximumWeightInKilograms: Int) = ???
def roundBin(generalWaste: List[GarbageCan], recycling: List[GarbageCan], diameterInMeters: Double) = ???
}
ComputeOptimalBinPacking.compressedSquareBin(wasteBins, recyclingBins, 100)
ComputeOptimalBinPacking.compressedSquareBin(wasteBins, recyclingBins, 200)
ComputeOptimalBinPacking.roundBin(wasteBins, recyclingBins, 0.8)