Menu
Coddy logo textTech

Moduły i include

Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 27 z 57.

Moduł to nazwana grupa metod. Nie może tworzyć obiektów, ale klasa może go include, a wtedy każda instancja ma metody modułu, tak jakby definiowała je klasa. Nazywa się to domieszką:

module Greetable
  def greet
    "Hello, I am #{name}"
  end
end

class Person
  include Greetable
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

puts Person.new("Ada").greet

Wynik:

Hello, I am Ada

Metody modułu mogą wywoływać metody udostępniane przez klasę, takie jak name powyżej. Dzięki temu jeden moduł może służyć bardzo różnym klasom, o ile każda z nich udostępnia to, czego używa moduł:

module Greetable
  def greet
    "Hello, I am #{name}"
  end
end

class Robot
  include Greetable

  def name
    "R2"
  end
end

class City
  include Greetable

  def name
    "Paris"
  end
end

puts Robot.new.greet
puts City.new.greet

Wynik:

Hello, I am R2
Hello, I am Paris

Klasa ma tylko jedną nadklasę, ale może zawierać dowolną liczbę modułów. include? sprawdza, czy klasa zawiera moduł, a moduł pojawia się w ancestors, zaraz po klasie — właśnie tam Ruby szuka jej metod:

module Swimmer
  def swim
    "swimming"
  end
end

module Flyer
  def fly
    "flying"
  end
end

class Duck
  include Swimmer
  include Flyer
end

d = Duck.new
puts "#{d.swim}, #{d.fly}"
puts Duck.include?(Flyer)
p Duck.ancestors.take(3)

Wynik:

swimming, flying
true
[Duck, Flyer, Swimmer]

Moduły grupują też powiązane klasy i stałe pod jedną nazwą, przestrzenią nazw, dzięki czemu nazwy się nie pokrywają. Shop::Item i Game::Item to różne klasy:

module Shop
  TAX = 0.2

  class Item
    def label
      "shop item, tax #{TAX}"
    end
  end
end

puts Shop::Item.new.label
puts Shop::TAX

Wynik:

shop item, tax 0.2
0.2
challenge icon

Wyzwanie

Łatwy

Uzupełnij moduły i klasy. Greetable#greet zwraca Hello, I am Ada, używając name obiektu. Walkable#walk(steps) dodaje kroki do licznika przechowywanego w @steps (przy pierwszym wywołaniu zaczynającego od nil) i zwraca Ada walked 30 steps, czyli bieżącą sumę. Person zawiera oba moduły; Robot zawiera tylko Greetable, a jego nazwa to R-, po którym następuje numer seryjny.

Dostarczony kod tworzy osobę i robota na podstawie pierwszego wiersza (Ada 7), następnie wykonuje polecenia greet p, greet r lub walk 10 (dla osoby), wypisuje wynik każdego z nich, a na końcu robot walks: false.

Twój kod umieść w plikach greetable.rb, walkable.rb, person.rb i robot.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

require_relative 'greetable'
require_relative 'walkable'
require_relative 'person'
require_relative 'robot'

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input = []
while (line = gets)
  input << line.chomp
end
name, serial = input[0].split
person = Person.new(name)
robot = Robot.new(serial)
input.drop(1).each do |line|
  command, arg = line.split
  if command == "walk"
    puts person.walk(arg.to_i)
  else
    target = arg == "p" ? person : robot
    puts target.greet
  end
end
puts "robot walks: #{Robot.include?(Walkable)}"
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Ruby online