Visibility

It's possible to restrict visibility and encapsulate code in the OOP tools Crystal provide.

The default behavior of an object is that it's visible under the namespace it's defined, but not to the outside. Unless you restrict the visibility of a method, it's public by default. You can use private or protected keywords to restrict this visibility.

An example of using a private method:

class Person
  def initialize(@name : String)
  end

  private def greet(message : String)
    p message
  end

  def greeter
    greet "Hi, #{@name}"
  end
end

class Employee < Person
  def greeter
    super
    p "Welcome to the office."
  end
end

p = Person.new("John")
p.greeter # => "Hi, John"

e = Employee.new("Mike")
e.greeter # => "Hi, Mike" "Welcome to the office"

An example of using a protected method:

class Person
  def initialize(@name : String)
  end

  protected def greet(message : String)
    p message
  end

  def greeter
    greet "Hi, #{@name}"
    self.greet "Hi, #{@name}"
  end
end

class Employee < Person
  def greeter
    person = Person.new("Jan")
    person.greet("Hi from the employee class") # => Works, because Employee is a person
  end
end

p = Person.new("John")
p.greeter # => "Hi, John"

e = Employee.new("Mike")
e.greeter # => "Hi, Mike" "Welcome to the office"

class Machine
  def greeter
    emp = Employee.new("David")
    emp.greet("Hi from the machine") # => Error: protected method 'greet' called for Person
  end
end