Ruby on Rails 網站程式設計基礎班
LESSON 4
Quiz 1
Welcome to Ruby on Rails!
Your First Rails App
$rails new my_app_name
Bundle Install
$rails new my_app_name
Self
# 現在我們知道用 attr_accessor,Ruby 會自動把 getter
# 和 setter method 產生出來
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "Hello, my name is #{name}"
end
# 但假設說我需要在 class 裡面其他的 instance method 裡
# 呼叫 getter 和 setter method
def change_info(n, a)
# 希望能像在使用 setter method 一樣, bob.name = "Boob"
name = n
age = a
end
end
bob = Person.new("bob", 17)
# 用 change info 改變 bob 的 name 和 age
bob.change_info("Bob", 30)
puts bob.name
puts bob.age
# => bob
# => 17
# 但是 bob 的資料卻沒變,為什麼?
# ruby 以為我們在 change_info 裡的 name 和 age 是指變數而不是 getter methods
More Self
# self 可用於:
# 1. 在 class 裡呼叫 setter / getter / instance methods
# 2. 宣告 class method 時
# 但是 self 本身是什麼?
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "Hello, my name is #{self.name}"
end
# 用這個 method 把 self 印出來
def who_am_i
puts self
end
end
bob = Person.new("bob", 17)
bob.who_am_i
# <Person:0x007ff1ba087dd0> self 在 instance method 裡
# 是指呼叫 instance method 的 object
# 所以在 instance method 裡面 self.age = bob.age
More Self
class Person
attr_accessor :name, :age
#今天我要是在class裡,instance methods 外看 self
puts self
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "Hello, my name is #{self.name}"
end
end
# => Person
# 所以在 class 裡面,instance method 外面,self 是指 class 自己
# 在在 class 裡面,instance method 裡面,self 是指被創出的某 object
Class Methods
# class 可以想像成是物件的模板/藍圖,但是他本身也可以被定義一些 method
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
# 定義 class 自己的 method
def self.hello
puts "hello, i am Person Class"
end
end
# 呼叫方式
Person.hello
#=> hello, i am Person Class
Class Variables
# 如果說 instance variable 是綁定物件的資料,那 class variable
# 就是綁定 class 本身的資料
class Person
attr_accessor :name, :age
# 宣告時前面加兩個 @@
@@number_of_people = 0
def initialize(name, age)
@name = name
@age = age
# 每創一個新的 object,就會被加一次
@@number_of_people += 1
end
def self.hello
puts "hello, i am Person Class"
end
# 回傳 @@number_of_people
def self.info
@@number_of_people
end
end
# 呼叫方式
puts Person.info
bob = Person.new("Bob", 17)
puts Person.info
# => 1
sam = Person.new("Sam", 32)
puts Person.info
# => 2
Constants
# constant 就是有些時候會遇上一些在程式裡不應改變的變數
# 像是圓周率、稅率、法定成年的年紀 etc.
class Person
# 宣告 constant,全部大寫
LEGAL_AGE_TO_DRIVE = 16
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
# 看這個人是否已到可以考駕照的年齡
def can_drive?
if self.age >= LEGAL_AGE_TO_DRIVE
puts "yes #{self.name} can drive"
else
puts "no #{self.name} can't drive"
end
end
end
bob = Person.new("Bob", 17)
bob.can_drive?
#=> yes Bob can drive
Class Inheritance
# 我們希望在建立新的 class 時,新的 class 也包含了舊的 class 的方法和特性
# 這時就可以使用 inheritance(繼承)
# 讓我不用重新寫很多東西
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "hello, my name is #{self.name}"
end
end
# 使用 < 來代表繼承
class Engineer < Person
end
class Salesman < Person
end
bob = Engineer.new("Bob", 17)
sam = Salesman.new("Sam", 32)
bob.greet
sam.greet
# => hello, my name is Bob
# => hello, my name is Sam
# Engineer 和 Salesman 繼承了 Person 的 greet 方法
Super
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
"hello, my name is #{self.name}"
end
end
# 如果我希望在改變 Engineer 的 greet
class Engineer < Person
# override (覆寫) 原本 Person 的 greet
def greet
# super 會呼叫 parent class 裡面同樣名字的 method
# 注意 super 只能在 method 裡面使用
puts super + ", I know how to write Ruby"
end
end
bob = Engineer.new("Bob", 17)
bob.greet
#=> hello, my name is Bob, I know how to write Ruby
Module
# 可把 module 想像成工具箱,本身並不是 class
# 不可 new,只能被 include 到其他 class 裡面使用
module Knowledge
def math
puts "I know math"
end
end
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "hello, my name is #{self.name}"
end
end
class Engineer < Person
include Knowledge
def greet
puts "I am an Engineer, my name is #{self.name}"
end
end
bob = Engineer.new("Bob", 17)
bob.math
# => I know math
Method Override
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "hello, my name is #{self.name}"
end
end
# 如果我希望在改變 Engineer 的 greet
class Engineer < Person
# override (覆寫) 原本 Person 的 greet
def greet
puts "I am an Engineer, my name is #{self.name}"
end
end
# 創立一個叫 German 的子類別
class German < Person
# override (覆寫) 原本 Person 的 greet
def greet
puts "Hallo, mein name ist #{self.name}"
end
end
bob = Engineer.new("Bob", 17)
martin = German.new("Martin", 20)
bob.greet
martin.greet
#=> I am an Engineer, my name is Bob
#=> Hallo, mein name ist Martin
Method Lookup
class Engineer < Person
include Knowledge
def greet
puts "I am an Engineer, my name is #{self.name}"
end
end
bob = Engineer.new("Bob", 17)
bob.math
# => I know math
# 尋找 Engineer 的祖先們
puts Engineer.ancestors
# Engineer
# Knowledge
# Person
# Object
# Kernel
# BasicObject
# 一旦 object 呼叫了一個它的 Class 裡面沒有的 method
# 他就會依序找他所有的祖先,若找到了有這個 method 的祖先,就使用這個祖先類別的 method
Public Method
# method 有三種不同的存取限制
# public 就是所有的人都可以直接存取
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
# greet 就是 public method
def greet
puts "hello, my name is #{self.name}"
end
end
#可以在程式的任何地方被使用
Private Method
# private 是只有在類別內部才可以存取
# 適用於有些時候,你希望一些 method 不會被程式的其他地方使用到(像是金流、身分證字號 etc.)
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "hello, my name is #{self.name}"
end
def identity
#只能在 class 裡面被其他 instance method 呼叫,前面不能加 self
puts "secretly, #{secret_method}"
end
private # 先寫 private 關鍵字
def secret_method
"I am Iron Man!"
end
end
bob = Person.new("bob", 17)
bob.identity
# secretly, I am Iron Man!
# private method 不可直接被物件呼叫
bob.secret_method
#=> private method `secret_method' called
#=> for #<Person:0x007ff182033498 @name="bob", @age=17> (NoMethodError)
Protected Method
# protected 是介於 public 和 private 之間
# 從 class 外面來看,protected 就像 private,不能被物件使用
# 從內部看,它就像一般的 method,可用 self 呼叫
class Person
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
def greet
puts "hello, my name is #{self.name}"
end
def identity
#在 class 裡面可被其他 instance method 呼叫,就像一般
puts "secretly, #{self.protected_method}"
end
protected # 先寫 protected 關鍵字
def protected_method
"I am Spider Man!"
end
end
bob = Person.new("bob", 17)
bob.identity
# secretly, I am Spider Man!
bob.protected_method
# => protected_class.rb:31:in `<main>': protected method `protected_method' called for
# => #<Person:0x007fb9f3033428 @name="bob", @age=17> (NoMethodError)
Ruby Style Guide
Homework 2
- Refactor Rock Paper Scissors in Object Oriented Style
- 加上能上使用者輸入名字的功能,並會印出加上使用者名字的結果
- Push to github
ntu_ror_261_lesson4
By Eugene Chang
ntu_ror_261_lesson4
- 943