物件導向的特色

常常聽到別人說物件導向、物件導向,一直以來都搞不懂,而且在實作的時候不容易察覺到
今天就來介紹物件導向的幾個特色

  • 封裝(Encapsulation)
  • 繼承(Inheriitance)
  • 多型(Polymorphism)

封裝(Encapsulation)

封裝是,只公開必要的介面,強迫外部的使用者只能透過介面做溝通,隱藏內部的資料或是邏輯,
無法干涉也無法看見內部的細節,而不需要了解物件內部是怎麼運作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Cat
#initialize可以定義類別屬性
def initialize(name)
@name = name
end

#定義一個類別方法,公開的方法,發出聲音的方法,是貓的行為
def sound
"meow meow"
end
end

#產生一個貓的物件,名字是Lily
cat1 = Cat.new("Lily")

#呼叫公開的方法
puts cat1.sound

貓的類別裡面
有貓的屬性
有一個貓的公開方法sound
封裝就是把屬性和方法包裝在一個單元裡面,外部可以透過物件來呼叫這個方法,讓貓發出聲音,但是外部的使用者不知道貓是如何發出的

繼承(Inheriitance)

允許子類別(subclass)可以繼承另一個父類別(superclass),去繼承父類別的屬性和方法。
重複性的類別在父類別上定義,子類別就可以做細節的屬性以及方法,這樣有益於代碼重用和建立結構化的層級。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal
def sound
puts "Animals can produce sounds"
end
end

class Cat < Animal
def speak
puts "cat meow meow"
end
end

cat2 = Cat.new
cat2.speak # cat meow meow

多型(Polymorphism)

意思是名稱完全相同的方法,但是根據傳入不同的參數,而有執行不同的動作

  1. 多載(Overloading)

  2. 複寫(Overriding)

以複寫作為範例(使用ruby on rails)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Animal
def sound
"Animals can produce sounds"
end
end

class Dog < Animal
def sound
"Dog howl howl"
end
end

class Cat < Animal
def sound
"Cat meow meow"
end
end

class Pig < Animal
def sound
"Pig oink oink"
end
end

# 建立動物的陣列
animals = [Dog.new, Cat.new, Pig.new]

# 讓每種動物發出聲音
animals.each do |animal|
puts animal.sound
end

建立了一個父類別Animal類別,讓Dog、Cat、Pig都繼承這個父類別
接下來,在各個子類別複寫sound方法,更細部描述每種動物的聲音
最後產生一個陣列包含不同動物的物件,使用迴圈讓每個動物發出聲音
不同類別的物件可以呼叫相同的方法sound,但根據物件的實際類別而執行不同的動作

在Javascript程式語言,Reference Type和Value Type是兩種不同的資料型別,它們在記憶體中的儲存和操作方式不相同。

Value Type

儲存的是數據本身
資料存放於Stack

Value type變數,這個變數會儲存數據本身

Value type有以下資料型態

  • number(包括整數、浮點數)
  • string
  • boolean
  • undefined
  • null
  • symbol

當將一個Value type變數賦值給另一個變數時,將複製實際的數據

用Javascript舉例子

1
2
3
4
5
6
let a = 10
let b = a
b = b + 1

console.log(`a = ${a}`) //印出a = 10
console.log(`b = ${b}`) //印出b = 11

Reference Type

儲存的是記憶體位置
資料存放於Heap

Reference type有以下資料型態

  • object(包括class)
  • function
  • array

當一個reference type的變數賦值給另一個變數時,它們將指向同樣的記憶體位置

用Javascript舉例子

1
2
3
4
5
6
let a = [1,2,3]
let b = a
b.push(7)

console.log(`a = ${a}`) //印出a = 1,2,3,7
console.log(`b = ${b}`) //印出b = 1,2,3,7

這個例子中
變數a是array陣列,變數a屬於reference type,儲存的是記憶體位置
a賦值給b,它們兩個變數指向同一個記憶體位置
變數b加進7之後
最終,a和b指向的記憶體位置的數值變成[1,2,3,7]

另外
我們可以用”比較運算符”去測試
=== 值和類型這2個是否完全相等
== 值是否相等

1
2
3
4
5
let c = [4,5]
let d = [4,5]

console.log(c === d) //false
console.log(c == d) //false

這個例子中,為什麼c怎麼樣都不等於d?

由於array陣列是Reference Type
===和==變成比較的是記憶體位置
c的記憶體位置和d的記憶體位置完全不同
所以都是false

除非改成以下程式碼

1
2
3
4
5
let c = [4,5]
let d = c

console.log(c === d) //true
console.log(c == d) //true

將變數c賦值給變數d,它們指向同一個記憶體位置

今天來實作一個函數,針對陣列中的奇數數字做加總

用Javascript撰寫

迴圈的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function oddSum(arr) {
let sum = 0;
for(let i = 0; i < arr.length; i++) {
if(arr[i] % 2 ===1) {
sum += arr[i]
}
}
return sum;
}

// 測試
const input = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const result = oddSum(input);
console.log(result);
// 25

函數function命名為oddSum,括號裡面名字(arr)代表陣列
一開始提供容器名稱是sum,初始值是0
用迴圈的方式,在陣列裡面一個一個跑
從陣列[0]開始跑,跑到陣列的最後一個數就結束迴圈
除以2會留下1的餘數(也就是奇數)
sum = sum + arr[i]
最後return sum

陣列filter、reduce方式

1
2
3
4
5
6
function OddSum(arr) {
const oddNumbers = arr.filter(num => num % 2 === 1);
const sum = oddNumbers.reduce((acc, curr) => acc + curr, 0);
return sum;
}

arr.filter(num => num % 2 === 1);
利用filter先過濾出奇數,符合num % 2 === 1這個條件的值會留下來,奇數會保留在陣列裡面

oddNumbers.reduce((acc, curr) => acc + curr, 0)
接下來,有了奇數oddNumbers之後,計算陣列裡面的數值

reduce進階用法可以參考MDN

參考資料
Array.prototype.filter()
Array.prototype.reduce()

用Ruby on rails撰寫

迴圈的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def sum_of_odd_numbers(arr)
sum = 0

arr.each do |num|
sum += num if num.odd?
end

return sum
end

// 測試
input = [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = sum_of_odd_numbers(input)
puts "陣列中奇數數字的總和為: #{result}"

如果用Ruby on rails撰寫
一樣先給容器sum
迴圈利用each的方法
由於Ruby on rails有.odd這個東西,可以直接檢查是不是奇數
最後做return sum

select、sum的方式

1
2
3
4
5
6
7
8
9
def sum_of_odd_numbers(arr)
sum = arr.select { |num| num.odd? }.sum
return sum
end

// 測試
input = [1, 2, 3, 4, 5, 6, 7, 8, 9]
result = sum_of_odd_numbers(input)
puts "陣列中奇數數字的總和為: #{result}"

Ruby on rails 有select方法, 在block設定條件{ },符合條件就會留下
條件是odd
去篩選陣列裡面的元素到一個新的陣列裡面
最後做sum,這個也是Ruby on rails本身有的方法

參考資料
ruby-selcet
ruby-sum

什麼是物件Object?

物件是從類別Class所創造出來的實體Instance
每個物件都有自己的狀態State(由類別的屬性定義)和行為Behavior(由類別的方法定義)。
有了類別之後,就可以做很多不同的物件

什麼是類別Class?

譬如一隻貓可以是一種類別,
物件的狀態,有貓的”毛色”以及”品種”
物件的行為,有貓的”聲音”

用Ruby on rails來舉一個例子,幫助了解實際的運用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#定義一個類別
class Cat

#initialize可以定義類別屬性
def initialize(name, breed, color)
@name = name
@breed = breed
@color = color
end

#定義一個類別方法,是貓的行為
def sound
"meow meow"
end

#定義一個類別方法
def check_info
"My name is #{@name},I'm #{@breed},my color is #{@color}"
end

end


#接下來,從貓類別創造出不同的物件
cat1 = Cat.new("Jane","Mix","Orange")
cat2 = Cat.new("Olive","Munchkin","Grey", )
cat3 = Cat.new("Cliff","Siamese","White")

# 調用物件身上的方法
puts cat1.sound #meow meow
puts cat2.check_info # My name is Olive,I'm Munchkin,my color is Grey"

這樣就完成了Cat類別,
有@name、@breed、@color總共3個實體變數,
定義貓的名字、品種、顏色;
有sound方法、check_info方法
知道貓類別的聲音
知道貓類別的基本資訊
每個物件都有屬於自己的狀態和行為
也可以呼叫方法

參考資料

類別(Class)與模組(Module)

寫了Routes之後

1
2
3
4
5
Rails.application.routes.draw do

resources :articles

end

現在來建立一個controller
依照Ruby on rails的慣例,當初Routes怎麼命名的,Controller就怎麼命名
這邊是articles做範例

閱讀全文 »

Routes的角色

簡單來說,Routes就像是服務台一樣,讓所有來拜訪的使用者指引方向
我拿華泰名品城做為比喻,華泰名品城這麼大的園區,有一期二期三期園區
走一走很容易迷路

這時候就需要服務台幫忙,櫃台會依據使用者的需求,詢問對應的部門,美食餐飲部、電影娛樂部、顧客服務部、精品部等等

找到部門之後,請部門提供相關的資料
Routes會導覽到某Controller,Controller的action幫你做事情;只要任一個沒有對應的話,會出現HTTP 404錯誤的訊息

MVC

閱讀全文 »

CORS 代表跨來源資源共用(Cross-Origin Resource Sharing)。它是一種瀏覽器的機制,用於限制網頁應用程式在不同來源(主機host、協定protocol、端口port)之間的資源共用。這是出於安全考量,以確保一個網頁應用程式只能請求和存取它自己的來源資源,而不容易被其他不受信任的網站濫用。

閱讀全文 »
0%