BrainLikeADullPencil
BrainLikeADullPencil

Reputation: 11653

Ruby: 'new' without a class

My understanding of Ruby was that the 'new' keyword was always combined with a class name to create a new instance of a class. In the code below, found at https://gist.github.com/e9c0da1a6e92dd12cbc7, which was submitted as a solution to a Ruby Programming Challenge for Newbies contest, the author uses the 'new' keyword three times without instantiating a class.

In one case, new(0,0) is assigned to a constant CLOSED. In another case, new(open,close) is a return value from a function. Why do it this way? What is 'new' doing when it's used this way? what is it creating?

class OpenHours

    attr_reader :open, :close

    def initialize(open, close)
      @open, @close = open, close
    end

    def duration
      @duration ||= @open < @close ? @close - @open : 0
    end

    CLOSED = new(0, 0)                #first new


    def self.parse(open, close)
      open  = Time.parse(open)
      close = Time.parse(close)


      open  = TimeUtils::seconds_from_midnight(open)
      close = TimeUtils::seconds_from_midnight(close)


      new(open, close)                        #second new

    end

    def offset(seconds)
      self.class.new([@open, seconds].max, @close)     #third new
    end

  end

Upvotes: 8

Views: 1968

Answers (3)

Andrew Grimm
Andrew Grimm

Reputation: 81500

OpenHours::CLOSED is an instance of OpenHours

irb(main):034:0> OpenHours::CLOSED
=> #<OpenHours:0x3ee2e85d @open=0, @close=0>
irb(main):035:0> OpenHours::CLOSED.class
=> OpenHours

To be honest, I don't know what they're doing here. I think it's bad code.

Reply to comment: If you do foo = OpenHours.parse(open, close), then the instance will be assigned to foo

Upvotes: 0

sawa
sawa

Reputation: 168091

When the receiver is self, the receiver can be omitted. The first two new calls that you are questioning are called within the context of OpenHours, which means that self is set to OpenHours. Therefore new without the explicit receiver is equivalent to self.new and OpenHours.new. In your third example, the context is an instance of OpenHours. self refers to that instance, and self.class refers to OpenHours, so self.class.new is equivalent to OpenHours.new. In all cases, the created object is an instance of OpenHours.

Upvotes: 7

yfeldblum
yfeldblum

Reputation: 65435

In Ruby, new is not an operator or keyword. It is an instance method of Class instances. For example, the object OpenHours is a class, and therefore is an instance of Class, and therefore has an instance method new.

Upvotes: 6

Related Questions