Search code examples
oopcrystal-lang

Crystal - How to have shared attributes and/or type among subclasses of parent


I believe this is a general OOP question, but I'm using Crystal insofar as that matters.

What is the right way to handle a situation where I have child classes that need to share a type but that type isn't the parent. For example, let's say I have animals: cats and dogs, and I also have baby animals: kittens and puppies. I want the kittens and puppies to be their own type with their own set of "parent" methods.

class Animal
end
class Dog < Animal
end
class Cat < Animal
end
class Puppy < Dog
  property? needs_milk = true
end
class Kitten < Cat
  property? needs_milk = true
end

I know that if all I needed was some properties or methods I could do this via a mixin:

module BabyAnimal
  property? needs_milk = true
end

but for my actual use case, I want to guarantee that all members of an array "are" BabyAnimals (and thus have baby animal methods and properties) i.e.

[] of Kitten | Puppy

So it feels like inheritance is the only / right way to do this.

Or am I missing something?


Solution

  • Modules are part of the type hierarchy. If you use the type restriction BabyAnimal, you can be assured that it only matches types that include that module.

    Kitten.new.is_a?(BabyAnimal) # => true
    
    array = [] of BabyAnimal
    array << Kitten.new
    array << Puppy.new