iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
Software Development

Dart 語言 - 開啟 Flutter 的鑰匙系列 第 15

Day 15:方法(Method)、getter 以及 setter

  • 分享至 

  • xImage
  •  

上一篇,我們介紹了類別。類別裡面的成員有屬性以及函數。

Methods are functions that provide behavior for an object.

接下來,我們將以方法 (Method) 來稱呼類別裡面的函數。

實體方法 (Instance methods)

this

關鍵字 this,表示該類別。在類別的方法內使用 this,可以使用定義於同類別但在方法外的屬性。

import 'dart:math';

class Point{
	double x, y;
	Point(this.x, this.y);

	double distanceTo(double x, double y){
		var dx = this.x - x;
		var dy = this.y - y;
		return sqrt(dx*dx + dy*dy);
	}
}

我們也可以將自己存在的類別以引數方式傳入,

import 'dart:math';

class Point{
	double x, y;
	Point(this.x, this.y);

	double distanceTo(Point other){
		var dx = x - other.x;
		var dy = y - other.y;
		return sqrt(dx*dx + dy*dy);
	}
}
  • 方法 distanceTo 裡面的 x, y 因為沒有和傳入的引數名稱衝突,所以可以忽略 this。

getter、setter

針對類別的屬性,Dart 也提供了一組特別的方法來對屬性進行存取。

當實例化類別參考類別的屬性時,其實已經隱含了 getter/setter。

我們也可以利用關鍵字 get、set 設定屬性的 getter 、setter。

class Student{
	String first_name;	
	String last_name;
	int age;
	Student(this.first_name, this.last_name, this.age);

	String get full_name => '$first_name $last_name';
	set full_name(String value){
    final split_name = value.split(' ');
    first_name = split_name[0];
    last_name = split_name[1];
  }
}
  • setter 的回傳值為 void,可省略。

使用範例:

void main(){
	var student = Student('Alex', 'Chen', 18);
	print(student.fullname); // Alex Chen
	student.fullname = 'Michael Jordan';
	print(student.fullname); // Michael Jordan
	print(student.firstname);// Michael
	print(student.lastname); // Jordan
}
  • 若屬性不需特別修改,可以不需使用關鍵字 getter、setter。
  • 若屬性的值是經過運算得來的,可以使用 getter;設定屬性會影響到其他的屬性,使用 setter。

setter 或是方法(method)

上面的範例中,我們在 setter 同時設定了其他屬性的值。因為這些屬性是有關聯的。

我們也可以改用方法完成。

class Student{
	String first_name;	
	String last_name;
	int age;
	Student(this.first_name, this.last_name, this.age);

	String get full_name => '$first_name $last_name';

	void setFullName(String fullName){
		  first_name = fullName.split(' ')[0];
	    last_name = fullName.split(' ')[1];
	}
}

當外部的呼叫者呼叫了 setFullName() 時,同樣也會修改 first_name, last_name。

void main(){
	var student = Student('Alex', 'Chen', 18);
	print(student.fullname); // Alex Chen
	student.setFullName('Michael Jordan');
	print(student.fullname); // Michael Jordan
	print(student.firstname);// Michael
	print(student.lastname); // Jordan
}

不過,Effective Dart 建議

DO use setters for operations that conceptually change properties.

對於在概念上修改屬性的操作,使用 setters。

另外,如果屬性只有 setter 而沒有 getter。那麼,應該要將 setter 的運算改用方法完成。

class Student{
	String first_name;	
	String last_name;
	int age;
	Student(this.first_name, this.last_name, this.age);

	set full_name(String value){
    final split_name = value.split(' ');
    first_name = split_name[0];
    last_name = split_name[1];
  }
}
  • 試想,如果上例中只有 setter ,那麼用 setter 設定完 full_name 時,卻沒有辦法得到 full_name 的內容。這樣不是很奇怪嗎?
  • 如果只是需要同時修改 first_name 及 last_name,使用一個方法替代就可以了。

可見性 (Visibility)

預設類別中的每一個屬性,函數都是可以被外部呼叫者看到的。如果某些屬性與函數僅在類別內部使用,那麼必須要將屬性或是方法名稱前方加上下底線。

class SampleClass{
	String value1;
	String value2;
	String _privateValue1;
	int _privateValue2;
	
	void doSomething1(){
		...
	}
	void doSomething2(){
		...
	}

	void _privateDoSomething(){
		...
	}
}

如此一來,外部的呼叫者就無法呼叫函數或方法名稱開頭是為底線的物件。

小結

每個類別都有專屬的功能,不同的類別裡面包含著不同的屬性以及方法。

利用上一篇介紹的建構式,我們將值帶入類別內的屬性,本篇文章介紹了如何使用方法以及屬性的 getter 、setter。

setter 的功能看似與方法相近,但是 setter 比較接近修改屬性的操作。但是,如果一個屬性只有setter 而沒有 getter,是可以用方法替換的。

最後,設計類別時,不一定要將每一個類別內的成員都公開給外部參考,在名稱前方加上下底線,就可以將屬性或是方法的可見性限制在類別內,換句話說,外部的呼叫者就看不到該物件。


上一篇
Day14:類別與建構式
下一篇
Day 16:抽象類別 (Abstract class)
系列文
Dart 語言 - 開啟 Flutter 的鑰匙30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言