I'm making an android game in Kotlin and I'm wondering about the use of my enumeration. It looks like this:
package com.example.makemoremeat.enumerations
import com.example.makemoremeat.R
enum class ProductionInformation(
val initialNumber: Double,
val initialCost: Double,
val initialProduction: Double,
val initialProductionTime: Double,
val coefficientCostUp: Double,
val imageProduction: Int
) {
Chicken(1.0, 1.0, 0.1, 1.0, 1.13, R.drawable.production_work_in_progress),
Beef(0.0, 7.0, 0.7, 2.0, 1.14, R.drawable.production_work_in_progress),
Mutton(0.0, 49.0, 4.9, 4.0, 1.15, R.drawable.production_work_in_progress),
Pork(0.0, 343.0, 34.3, 8.0, 1.16, R.drawable.production_work_in_progress),
Rabbit(0.0, 2401.0, 240.1, 16.0, 1.17, R.drawable.production_work_in_progress),
Horse(0.0, 16807.0, 1680.7, 32.0, 1.18, R.drawable.production_work_in_progress),
Caribou(0.0, 117650.0, 11765.0, 64.0, 1.19, R.drawable.production_work_in_progress),
Fish(0.0, 823540.0, 82354.0, 128.0, 1.20, R.drawable.production_work_in_progress),
Dog(0.0, 5764800.0, 576480.0, 256.0, 1.21, R.drawable.production_work_in_progress),
Elephant(0.0, 40354000.0, 4035400.0, 512.0, 1.22, R.drawable.production_work_in_progress),
Bugs(0.0, 282480000.0, 28248000.0, 1024.0, 1.23, R.drawable.production_work_in_progress),
Vegan(0.0, 1977300000.0, 197730000.0, 2048.01, 1.24, R.drawable.production_work_in_progress),
Cultured(0.0, 13841000000.0, 1384100000.0, 4096.0, 1.25, R.drawable.production_work_in_progress)
}
And I use it this way:
class Production (
private val game: Game,
private val productionInformation: ProductionInformation
) {
val image = productionInformation.imageProduction
var numberPossessed = productionInformation.initialNumber
var actualCost =
productionInformation.initialCost * productionInformation.coefficientCostUp.pow(
numberPossessed - 1
)
var actualProduction = productionInformation.initialProduction
var actualProductionTime = productionInformation.initialProductionTime
[...]
Is it clean? Or else what would be the way to do in this case? Inheritance with 13 classes extending Production would be better? Thanks for your help !
CodePudding user response:
Inheritance with multiple classes would definitely be worse! There is nothing here that necessitates different classes. None of these items need a unique property or function type.
It is an OK pattern in some cases. But if you don't really need to enforce a specific, finite set of possible items, a regular class, maybe data
class, would be sufficient. For example, if you don't need to use when
statements on it to treat each possible member differently, or be able to iterate all possible values, then making it an Enum class doesn't really buy you anything, and it limits where you can define instances. Your code above suggests no reason why this shouldn't just be a data class.
Since you have many entries, possibly it should be loaded from a resource like a JSON file pre-prepared database file.
CodePudding user response:
enums
or "enumerated/enumaration data type", are widely used for selection constructs, use-cases where your logic would follow a certain path based on the enum
you provide, consider the following, each described by a simple requirement
Case 1
:
Cold or Hot food, if the customer ordered a cold food, serve the customer with a jacket, if the customer orders a hot food, give him a bucket of ice
enum class FoodOrderType {
COLD, HOT
}
somewhere in my code
val foodType = customer.getOrderedFoodType()
when (foodType) {
FoodOrderType.COLD -> {
// free jacket
}
FoodOrderType.HOT -> {
// a bucket of ice
}
}
Case 2
:
Depending on specific volume level of your car's current gasoline, make a decision whether to continue driving? get your wallet ready?, or look for a nearest gas station
enum class GasolineLevel {
FULL, HALF, QUARTER
}
somewhere in my code
val gasolineLevel = car.getGasolineLevel()
when (gasLevel) {
GasolineLevel.FULL -> {
// continue driving
}
GasolineLevel.HALF -> {
// get your wallet ready
}
GasolineLevel.QUARTER -> {
// look for the nearest station
}
}
You can see that most of the examples above revolves around how your code flow
will decide continuing, however in your question, it doesn't seem to warrant something for a "decisional" or "conditional" flow of code, its just an enum representing a series of characteristics Inherited
by certain constructs.
Personally I see your code falling into an Inheritance Design, where your
- Chicken
- Beef
- Mutton
- Pork
- etc...
inherits their characteristics
from ProductionInformation
like
class Chicken : ProductInformation{
...
}
or
class Beef: ProductInformation{
...
}
or better yet, keeping the context intact you should suffix your class names based on its context like the following
class ChickenProduct : ProductInformation {
...
}
or
class BeefProduct : ProductInformation{
...
}
There is nothing wrong with your code, but there are certain OOP principles that makes sense for certain use-cases.
Edit: I agree with Tenfour04, composition
is the most ideal design strategy for your use-case, instead of a bloated package/directory full of similar classes with different names, Prefer composition over inheritance