學習軌道
/
Crystal
Crystal
/
練習
/
Bellebrook 籃球聯盟
Bellebrook 籃球聯盟

Bellebrook 籃球聯盟

學習練習

簡介

Crystal 的模組有兩個用途:

第一個用途是建立命名空間,避免名稱衝突。 不過,它同時也會將程式碼分組,讓人更容易理解程式碼的用途。

第二個用途是定義混入,把程式碼分享給型別。

模組和類別很相似,但最主要的差別在於模組無法被實體化,因此沒有實體變數。

要宣告一個模組,使用 module 關鍵字,後面接模組名稱。

module Foo
end

命名空間

命名空間是一種將程式碼分組的方式。 這樣可以避免名稱衝突,也讓人更容易理解程式碼的用途。 當你想存取放在命名空間裡的常數或類別時,可以使用 :: 運算子。

module Foo
  class Bar
  end
end

Foo::Bar.new

當作混入使用

這在許多情況下都很有用,例如多個類別需要相同的「基底」功能,或是程式碼需要在互不相關的類別之間共用。 又或者,你想在彼此沒有關聯的類別之間共用程式碼。

把模組當作混入使用有兩種方式:第一種是使用 include 關鍵字,第二種是使用 extend 關鍵字。

這兩種方法都會讓常數提供給引入或擴充該模組的型別使用。

Include

Include 會讓模組中的所有方法,在引入該模組的型別上以實體方法的形式使用。 include 關鍵字應放在型別的最上方,後面接模組名稱。

module Foo
  def foo
    "foo"
  end
end

class Bar
  include Foo
end

Bar.new.foo # => "foo"

Extend

Extend 的運作方式和 Include 類似,但它不是讓方法以實體方法的形式使用,而是讓它們以類別方法的形式使用。 extend 關鍵字應寫在型別的最上方,後面接模組名稱。

module Foo
  def foo
    "foo"
  end
end

class Bar
  extend Foo
end

Bar.foo # => "foo"

Extend self

Crystal 中一個常見的模式,是在模組裡使用 extend self 模式。 這會讓模組中的所有方法,在模組本身以類別方法的形式使用。 也就是說,你不需要用 def self.method_name 語法把每個方法都指定給模組。

module Foo
  extend self

  def foo
    "foo"
  end
end

Foo.foo # => "foo"

說明

Bellebrook Basketball League 是一個由多支球隊組成的聯盟,每支球隊都有一份球員名單。 新賽季即將開始,他們需要建立一套新的售票系統來販售比賽門票。 上一賽季,他們在體育館入口販售門票,但隨著人氣暴漲,他們決定這一季改在線上售票,以應付增加的需求。

聯盟聯絡了你,請你建立一套系統來處理售票事宜。

1. 建立售票系統

首先,你需要建立一套售票系統來處理售票事宜。 這套售票系統需要能顯示一場比賽有多少張門票可供販售。

每場比賽都要建立一個名為 TicketSystem 的類別實例。 初始化的狀態應該包含以下資訊:

  1. 這場比賽有多少張門票可供販售。
  2. 比賽在哪座體育館舉行。

從引數建構初始化的狀態,引數分別表示可販售的門票數量,以及比賽舉行的體育館。 初始化的狀態應該由實例變數 @tickets_available 和 @stadium 組成。 這兩個變數應分別存放傳入的第一個和第二個引數。

TicketSystem.new(100, "Bellebrook")
# => #<TicketSystem:0x10f0b8 @tickets_available=100, @stadium="Bellebrook">

2. 取得可販售的門票數量

首先,你需要建立一個方法,回傳指定比賽可販售的門票數量。

在已定義的類別上方定義一個名為 TicketingReservation 的模組。 這個模組應該被包含進 TicketSystem 類別中。

在模組內定義一個名為 tickets_available 的方法。 這個方法應該回傳可販售的門票數量。

ticket_system = TicketSystem.new(100)
ticket_system.tickets_available
#=> 100

3. 訂購門票

你必須建立一個方法,檢查指定比賽是否還有門票。 比賽必須保留 100 張門票。 這是為了確保在體育館入口購票的人永遠都能買到票。

在 TicketingReservation 模組內定義一個名為 order_ticket? 的方法。 如果至少還有 100 張門票可供販售,這個方法應該回傳 true,否則回傳 false。 如果至少還有 100 張門票可供販售,這個方法還應該把可販售的門票數量減少 1。

ticket_system = TicketSystem.new(100)
ticket_system.order_ticket?
#=> true

4. 訂購訊息

售票系統的訊息必須讓使用者容易理解。 而且這些訊息應該讓人感到貼心,所以要包含使用者的名字。

如果購票成功,使用者應該會收到一則訊息,告訴他們購票成功、他們的票號,以及比賽在哪座體育館舉行。 票號應該是下單前可販售的門票數量。

如果購票成功,訊息應該長這樣:{name}, your purchase was successful, your ticket number is #{ticket_number}, and the game is played at the {stadium_name} stadium.。 如果購票失敗,訊息應該長這樣:{name}, your purchase was unsuccessful, there are not enough tickets available.。

在 TicketingReservation, 模組內定義一個名為 order_message 的方法,它接受一個引數 name,內含購買者的名字。 這個方法應該回傳包含該訊息的字串。

ticket_system = TicketSystem.new(100, "Bellebrook")
ticket_system.order_message("John")
#=> "John, your purchase was successful, your ticket number is #100, and the game is played at the Bellebrook stadium."
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Crystal Exercism

準備好開始 Bellebrook 籃球聯盟 了嗎?

註冊 Exercism,透過 26 個概念142 個練習 和真人引導來學習並精通 Crystal,全部免費。