Attempts to design an object model - using enums

I am trying to create an object model (for C #) and cannot find a better way to store data. I'll try to use a simple example to illustrate this!

I have a "pet" object that can be one of "cat", "dog", etc. So, I created a class "pet" with an enumeration "petType" to store this.

Now it gets tricky. If the "pet" is a "cat" then its "food" can be "fish", "milk", etc. If it is a "dog", then its "food" can be "meat", "cookies", or something like that.

Now I have to create a large enum for "fish", "milk", "meat" and "biscuits" and somehow code it so that "cat" cannot be assigned to "food.meat"? It wouldn't make sense for my "pets" class to have an enumeration of "catfood" and "dogfood" because that is not extensible and will end up containing many numbered enums.

Is there an elegant solution that I am not seeing?

+1


source to share


5 answers


Try # 2. Seems to be correct



interface IPet { }

class Cat : IPet
{
    public void eat(CommonFood food) { }
    public void eat(CatFood food) { }
}

class Dog : IPet
{
    public void eat(CommonFood food) { }
    public void eat(DogFood food) { }
}

interface IFood { }

abstract class CommonFood : IFood { }

abstract class CatFood : IFood { }

abstract class DogFood : IFood { }

class Milk : CommonFood { }

class Fish : CatFood { }

class Meat : DogFood { }

class Program
{
    static void Main(string[] args)
    {
        Dog myDog = new Dog();
        myDog.eat(new Milk()); // ok, milk is common
        myDog.eat(new Fish()); // error
    }
}

      

+2


source


First, the cat and dog should probably be subclassified from pet , suggesting that there are some common characteristics of all pets.



Further, I don't understand what you are planning to do with the food . Is there a pet as an object model , or will there be methods as it is that there is food as an argument ?

0


source


I don't know about your cat, but my cats eat meat and very little!

and scraps of dining tables like cookies are bad for dogs (and cats)

but as an aside, why are you wrapping up with enums? and why does your "pet" object have a "petType" property? A simple / direct representation would be the Pet class with subclasses of Cat and Dog, but a more practical representation would be the Pet interface, which can be applied to any Animal object.

0


source


I agree with Tautologistics about subclassing Cat and Dog Pet (or implementing the Pet interface!), Instead of having an explicit PetType enumeration and field. Explicit "type flags" are incompatible with true OO design.

When it comes to relationships with food, you can think about implementing two concepts:

  • The "business rule" for Pet, implemented using the method acceptsFood(FoodEnum food)

    . This method will be responsible for verifying the legality of the food prescription.
  • The "favorite food" property of any instance Pet

    (subclass) that allows an individual pet to identify a favorite food (from a set of foods that are actually accepted by its species).
0


source


It sounds like you need to consider cat and dog food as a kind of strategy and compose the right food with the appropriate pet using a simple factory.

Here's one option in Ruby.

class CatFood
  attr_reader :items

  def initialize
    @items = ['fish', 'milk']
  end
end

class DogFood
  attr_reader :items

  def initialize
    @items = ['meat', 'biscuits']
  end
end

class NoFood
  attr_reader :items

  def initialize
    @items = []
  end
end

class Pet
  attr_reader :food

  def initialize(food)
    @food = food
  end
end

class PetFactory
  def create_dog
    Pet.new(DogFood.new)
  end

  def create_cat
    Pet.new(CatFood.new)
  end

  def create_unknown_pet
    Pet.new(NoFood.new)
  end
end

      

0


source







All Articles