Search code examples
ruby-on-railsrubysubclassmixinssuperclass

ruby - One superclass , 2 subclasses and One common Method - Having an error


The following has Universe(superclass) , Common(module), FlatEarthBelievers(subclass) and RoundEarthBelievers(subclass). There is an error with the output and want to make it work, any pointers?

This is about inheritance and mixins, a scenario where child classes inherit from a common Parent and want to utilise the common methods that are not related to the Parent's behaviour. I want to be able to call the methods from the common module inside the Child class that includes/extends it . I have a confusion in its usage because I want to see those common methods as both class methods and instance methods.

 class Universe
      $knowledge = "Universe comprises of galaxies, stars, planets,  steroids, meteoroids, comets, etc"
       def  universe_comprises_of
       puts $knowledge
     end
    end

    ​module Common
      $earth_is = Hash.new
      def init(earth_is)
        $earth_is = earth_is
      end
       def statement
         puts  " Earth is " + $earth_is["attribute"].to_str
       end
    end

    class FlatEarthBelievers < Universe
      include Common
      earth_is = { :attribute => "Flat !" }
      init(earth_is)
    end

    class RoundEarthBelievers < Universe
       include Common
       earth_is = { :attribute => "Round like an Orange!" }
       Common.init(earth_is)
    end

    moron = FlatEarthBelievers.new
    moron.universe_comprises_of
    moron.statement

    sensible_person = RoundEarthBelievers.new
    sensible_person.universe_comprises_of
    sensible_person.statement

Solution

  • There are many things wrong with this code. Set aside the $ variable issue since that is discussed in the comments to your OP.

    To begin with, you do:

    moron = Flat_earth_believers.new
    

    But you don't have any classes named Flat_earth_believers. You probably meant FlatEarthBelievers.

    You include the Common module, which makes all the methods therein instance methods, but then you try to call them as class methods, here:

    class FlatEarthBelievers < Universe
      include Common
      earth_is = { :attribute => "Flat!" }
      init(earth_is) # this is calling a class method
    end
    

    and here:

    class RoundEarthBelievers < Universe
      include Common
      earth_is = { :attribute => "Round like an Orange!" }
      Common.init(earth_is) # this is calling a class method
    end    
    

    There's other stuff, but you get the idea.

    Anyway, I don't really know what you're trying to do, but I think I would just make Universe like:

    class Universe
      KNOWLEDGE = "Universe comprises of galaxies, stars, planets,  steroids, meteoroids, comets, etc"
    
      def  universe_comprises_of
        puts KNOWLEDGE
      end
    end
    

    And Common like:

    module Common
    
      def statement
        puts "Earth is #{self.class::EARTH_IS[:attribute]}"
      end  
    
    end
    

    Then FlatEarthBelievers like:

    class FlatEarthBelievers < Universe
      include Common
    
      EARTH_IS = { :attribute => "Flat!" }
    end
    

    Then you can do:

    moron = FlatEarthBelievers.new
    moron.universe_comprises_of
     => Universe comprises of galaxies, stars, planets,  steroids, meteoroids, comets, etc
    moron.statement
     => Earth is Flat!
    

    I will also note that Jörg W Mittag wishes to say:

    I am one of those Ruby Purists who likes to point out that there is no such thing as a class method in Ruby. I am perfectly fine, though, with using the term class method colloquially, as long as it is fully understood by all parties that it is a colloquial usage. In other words, if you know that there is no such thing as a class method and that the term "class method" is just short for "instance method of the singleton class of an object that is an instance of Class", then there is no problem. But otherwise, I have only seen it obstruct understanding.

    Let it be fully understood by all parties that the term class method is used above in its colloquial sense.