Ruby - Private vs Protected - What's the difference?

What’s the difference?

Private Methods Explained

@freddie = Person.new
@freddie.hows_it_going?
# => "oh dear, i'm in great pain!"

class Person   
    # public method
    def hows_it_going?
        how_are_your_underpants_feeling?
    end

    private

    def how_are_your_underpants_feeling? # private method
        puts "oh dear, i'm in great pain!"
    end
end

We can ask Freddie how things are going given it’s a public method. That’s perfectly valid. And it’s normal and accepted.

But…the only person who can know how Freddie’s underpants situation is, is Freddie himself. It would not do for random strangers to reach into Freddy’s underpants and test out the situation – no, no – it’s very, very private, and we don’t want to expose what’s private to the outside world.

@freddie.how_are_your_underpants_feeling?
# => # NoMethodError: private method `how_are_your_underpants_feeling?' called

Protected Methods Explained

Ok now what’s the deal with protected? Now consider this situation:

class Person
    
    protected

    def gimme_your_credit_card! # protected method
        puts "Fine. Whatever. Here it is: 1234-4567-8910"
    end
end

class Rib < Person
end

class Wife < Rib # wife inherits from Rib
    def i_am_buying_another_handbag_with_your_card(husband)        
        husband.gimme_your_credit_card!
    end
end

@husband = Person.new
@mrs = Wife.new
@mrs.i_am_buying_another_handbag_with_your_card(@husband)
# => puts "Fine. Whatever. Here it is: 1234-4567-8910"

We’re somewhat ok with mrs getting our credit card details, given mrs is flesh of our flesh, inherited from Person, but we don’t want random individuals getting access to our credit card details.

If we tried to do that outside the subclass, it would fail:

@mrs = Wife.new
@mrs.gimme_your_credit_card!
# => protected method gimme_your_credit_card! called for #<Wife:0x00005567b5865818> (NoMethodError)
Written on February 2, 2021