物件 = 狀態(名詞) + 行為(動詞)
透過物件導向程式設計,讓程式碼變得容易被理解與使用
類別就像是一個模型,透過這個模型可以製造出許多實體以下方程式碼為例
定義類別:
class Lily
def eat
puts " 好吃!"
end
end
產生實體:
luna = Lily.new #加上new就可以產生一個個實體
luna.eat #有實體就可以使用eat這個方法
#luna是實體Lily是類別
class Animal #把狗與貓共同會有的方法定義在上一層
def walk
end
def eat
end
end
class Dog < Animal #會繼承Animal裡的方法
end
class Cat < Animal #會繼承Animal裡的方法
end
kitty = Cat.new #kitty這個實體屬於貓類別
kitty.eat #因為貓類別繼承Animal所以他有eat這個方法
class Lily
def initialize #特別的方法
puts "hello!"
end
end
kitty = Lily.new
# hello!
#不需要呼叫方法,按執行就會出現
可使用參數
class Lily
def initialize(name,age)
@name = name #把 name 帶進 @name 實體變數上
@age = age
end
end
kitty = Lily.new("luna",18) #luna與18會帶進上方的initialize方法參數(name,age)
new 是創造一個實體,initialize 是這個實體產生後的初始化方法
class Lily #類別
def eat
puts "# 好吃!"
end
end
luna = Lily.new
luna.eat
#luna是實體,eat作用在luna上所以是實體方法
在定義方法前,一定要在方法名稱前加上 self
class Lily
def self.eat #一定要加上self
puts " 好吃!"
end
end
Lily.eat
#Lily是類別,eat是作用在Lily上所以是類別方法
一個@開頭,會存活在每個獨立的實體內,在實體內可自由取用的變數
class Lily
def initialize(name)
@name = name #1.把 name 帶進 @name 實體變數上
end
def name #getter
reture @name
end
def neme=(new_name) #setter
@name = new_name
end
end
kitty = Lily.new("luna") #2.在kitty裡會有一個 @name的實體變數
kitty.name #3.呼叫name方法時會回傳 @name這個變數,無法直接像js一樣取用
kitty.neam=("lily") # lily
以上圖為例,我先用 Lily 這個類別製造一個實體名叫 kitty,再用初始化這個方法將 name 帶進@name 變成實體變數,所以我 kitty 這個實體內有個@name 的實體變數,@name 只存活在 Lily 這個類別裡,所以我無法直接呼叫 name,只能透過 say 方法把@name 回傳回來。
在 Ruby 裡沒有屬性,所以取個值變得很麻煩,也因此有了 attr_reader/attr_writer/attr_accessor 來協助,以下為例
class Lily
attr_reader :name #只要有這個就不用在創造一個方法來回傳
attr_writer :name #只要有這個就不用創造一個方法來做 @name重新設定名字
attr_accessor :name #此方法等同與上述 2個方法
def initialize(name)
@name = name
end
end
kitty = Lily.new("luna")
puts kitty.neme #在這裡就可以顯示了
kitty.name = "lily" #在這裡可重新設定名字
@@開頭,在類別方法內可自由取用的變數
class Lily
@@counter = 0 #類別變數
def initialize
@@counter += 1
end
def self.counter
return @@counter
end
end
5.times {Lily.new} #進行5次初始化
p Lily.counter # 一樣要先創造一個self.counter的類別方法,才可以使用類別變數
# 5
class Lily
def hell0
end
end
class Lily
def world
end
end
kitty = Lily.new
kitty.hello #可執行
kitty.world #可執行
在 Ruby 裡兩個同名的類別不會覆蓋而是融合,也因為開放的關係我可以幫現有的類別加功能,甚至內建類別也做得到。類別裡的方法則不是這樣,方法同名會覆蓋。
class Lily
def eat #沒有明講就是public
end
private #不讓外部使用
def gossip
end
end
kitty = Lily.new
kitty.eat #外部可使用
kitty.gossip #因方法設定在private下,所以外部無法使用
private:不能有明確的訊息接收者,意思是可以透過別的方法來存取此方法,以下為例
class Lily
def eat
gossip
end
private
def gossip
end
end
kitty = Lily.new
kitty.eat #private不能有明確接收者,所以存取gossip方法,先要將他放進public方法裡,才可存取
private 與 protected 差在,在 public 的方法裡 protected 可以在方法前加 self,以下為例
class Lily
def eat
self.gossip
end
protected
def gossip
end
end
kitty = Lily.new
kitty.eat #protected不論有沒有self都存取得到,但private不可以