Skip to content

Instantly share code, notes, and snippets.

@laurencer
Created August 1, 2014 06:04
Show Gist options
  • Save laurencer/910a0d6873f7f6df8326 to your computer and use it in GitHub Desktop.
Save laurencer/910a0d6873f7f6df8326 to your computer and use it in GitHub Desktop.
When to use an Object with a Apply Method

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment