flutter學習4 - dart語言學習

一、Dart中的變量

1.1、變量

var :解釋器自動推斷變量的類型。注意:再次賦值的類型不一樣會報錯
dynamic:變量類型可動態改變
final:最終變量,不可變的變量。在聲明時,需要對變量進行賦值
const:常量,不可變的變量。在聲明時,需要對變量進行賦值

注意:無論什么類型的變量,如果不對其進行賦值,那么它的默認值都是 null。

// 以下代碼會報錯:
var name = "變量"; 
 name = 1;

// 以下代碼不會報錯
dynamic age = 26; 
age = "26";

進行推斷

1.2 變量的數據類型

Dart 中內置了 7 類特殊的數據類型:
numbers:數值類型
strings:字符串類型
booleans:布爾類型
lists:列表類型
maps:圖類型
runes:字符類型
symbols:符號類型

1.2.1 數值類型

在 Dart 中,數值類型有兩種,分別為 int 和 double。

如果使用 0x 開頭定義數值,就表示使用十六進制數值。

如果一個數值包含小數,就需要將其定義為 double 類型。

e 符號表示科學計數法。

整型數值是可以直接賦值給浮點型變量的。

int a = 99; 
int b = 0xA1; 
print(a);//99 
print(b);//161

double c = 3.14; 
double d = 1.4e2; 
print(c);//3.14 
print(d);//140.0

double e = 1; 
print(e);//1.0

數值類型常用屬性

var count1 = 1; 
var count2 = 1.1; 

//runtimeType 屬性獲取運行時類型
print(count1.runtimeType);//int 
print(count2.runtimeType);//double

//獲取當前數值是否為有限值,返回 true 或者 false 
print(count1.isFinite); 

//獲取當前數值是否為無限值,返回 true 或者 false 
print(count1.isInfinite); 

//獲取當前數值是否為 NaN,NaN 描述非數值
print(count1.isNaN); 

//獲取當前數值是否為負數 
print(count1.isNegative); 

//獲取當前數值的符號。若返回 1,則表示為正數;若返回-1,則表示為負數;若返回 0,則表示當前數值為 0 
print(count1.sign); 

//獲取存儲當前數值需要的最少位數,int 類型獨有的屬性
print(count1.bitLength); 

//獲取當前數值是否為偶數,int 類型獨有的屬性
print(count1.isEven); 

//獲取當前數值是否為奇數,int 類型獨有的屬性
print(count1.isOdd);

數值類型常用方法

var count1 = -1; 
var count2 = 1.1; 

//返回當前數值的絕對值
print(count1.abs()); 

//返回不小于當前數值的最小整數
print(count2.ceil());//2 

//返回不小于當前數值的最小整數,返回數值為浮點類型
print(count2.ceilToDouble());//2.0 

//返回指定范圍內離當前數值最近的數值,如果當前數值在范圍內,就直接返回
print(count1.clamp(1,10)); 

//將當前數值與傳入的參數進行比較:如果大于傳入的參數,就返回 1;如果小于傳入的參數,就返回-1;如果等于傳入的參數,就返回 0 
print(count1.compareTo(0)); 

//返回不大于當前數值的最大整數
print(count2.floor());//1 

//返回不大于當前數值的最大整數,返回數值為浮點類型
print(count2.floorToDouble());//1.0 

//獲取當前數值除以參數后的余數
print(count1.remainder(5)); 

//獲取離當前數值最近的整數,四舍五入
print(count2.round()); 

//獲取離當前數值最近的整數,四舍五入,返回浮點數
print(count2.roundToDouble()); 

//將當前數值轉換成浮點數返回
print(count1.toDouble()); 

//將當前數值轉換成整型數返回
print(count2.toInt()); 

//將當前數值轉換成字符串返回
print(count1.toString()); 

//將當前數值的小數部分丟棄后返回整數值
print(count2.truncate()); 

//將當前數值的小數部分丟棄后返回整數值,浮點類型
print(count2.truncateToDouble());

int類型獨有的方法

var num1 = 35; 
//獲取當前數與傳入參數的最大公約數
print(num1.gcd(7));//7 
//求模逆運算
print(num1.modInverse(6)); 
num1 = 2; 
//對當前數值進行冪運算,之后進行取模運算 
print(num1.modPow(3,5));//2 的 3 次方除以 5 取余數

1.2.2 字符串類型

可以使用單引號或者雙引號來創建字符串

$來進行字符串的格式化

字符串也支持直接使用“+”運算符來進行拼接

即使不使用運算符,相鄰的字符串也會自行進行拼接

使用 3 對單引號或者 3 對雙引號可以進行多行字符串的創建

反斜杠進行字符轉譯

var name = "變量"; 
var str3 = "Hello ${name} $name"; 
var num1 = 3; 
var num2 = 4; 
var str4 = "3+4=${num1+num2}"; 
print(str3);//Hello 變量
print(str4);//3+4=7

// “+”運算符來進行拼接
var str1 = "Hello"; 
var str2 = 'World'; 
print(str1+str2);//HelloWorld

// 相鄰的字符串自行進行拼接
print('hello''world');//helloworld

// 3 對單引號或者 3 對雙引號創建多行字符串
var str5 = '''第一行
第二行
第三行'''; 
var str6 = """第一行
第二行
第三行""";

print('hello \'變量\'');//hello '變量'

常用屬性和方法

//獲取字符串的字符碼集合
print(str8.codeUnits);//[97, 98, 99] 
//獲取當前字符串是否為空字符串,返回布爾值
print("".isEmpty);//true 
//獲取當前字符串是否為非空,返回布爾值
print("".isNotEmpty);//false 
//獲取當前字符串長度
print(str8.length);//3 
//獲取類型
print(str8.runtimeType);//String

//通過下標獲取某個字符串中某個字符的 code 碼,下標從 0 開始
print("hello".codeUnitAt(0));//104 
//進行字符串比較,逐個字符進行 code 碼的比較
print("hello".compareTo('a'));//1 
//獲取當前字符串是否包含參數字符串
print("hello".contains('l'));//true 
//判斷當前字符串是否以某個字符串結尾
print("hello".endsWith("llo"));//true 
//判斷當前字符串是否以某個字符串開頭
print("hello".startsWith('h'));//true 
//獲取要進行匹配的字符串在當前字符串中的位置,如果沒找到,就返回-1 
print("hello".indexOf("l"));//2 
//獲取要進行匹配的字符串在當前字符串中的位置,逆向查找,如果沒找到,就返回-1 
print("hello".lastIndexOf("l"));//3 
//在左邊進行字符串位數補齊
print("hello".padLeft(10,"*"));//*****hello 
//在右邊進行字符串位數補齊
print("hello".padRight(10,"&"));//hello&&&&& 
//進行字符串替換,將匹配到的字符串替換成指定的字符串
print("hello".replaceAll("o","p"));//hellp 
//將指定范圍內的字符串進行替換,左閉右開區間
print("hello".replaceRange(0,3,"000"));//000lo 
//使用指定字符串作為標記對原字符串進行分割,結果會放進列表返回
print("hello".split('e'));//[h, llo] 
//進行字符串截取,左閉右開區間
print("hello".substring(1,3));//el 
//將字符串全部轉為小寫
print("Hello".toLowerCase());//hello 
//將字符串全部轉為大寫
print("hello".toUpperCase());//HELLO 
//將字符串首尾的空格去掉
print(" hello ".trim()); 
//將字符串首部的空格去掉
print(" hello".trimLeft()); 
//將字符串尾部的空格去掉
print("hello ".trimRight());
// 對字符串進行拷貝,使用*運算符
print("hello"*2);//hellohello
// 使用中括號來獲取集合內的某個元素
print("hello"[0]);//h

1.2.3 布爾類型

一種簡單的數據類型,其只有兩個字面量值:true 和 false。
使用 runtimeType 來獲取類型
調用 toString 方法來將布爾值轉換成字符串

bool a = true; 
bool b = false;
print(a.runtimeType);//bool

bool a = true; 
print(a.toString());//true

1.2.4 列表類型

列表用來存放一組數據,也被稱為數組。在 Dart 中,列表具體的數據類型由其中的元素類型決定。
想在列表中存放不同類型的數據,則可以將列表聲明成動態類型的。
列表類型可以通過構造方法來創建

下標超出了列表元素的個數,就會產生溢出異常。

List<int> list = [1,2,3,4];
List<dynamic> list = [1,2,3,4,"5"];

//創建長度為 5 的列表,默認使用 null 填充
var list2 = new List(5);//new 可以省略 [null, null, null, null, null] 
//創建指定長度的列表,并使用指定的值作為默認值
var list3 = List.filled(3,1);//[1,1,1] 
//通過另一個集合類型的數據來創建列表
var list4 = List.from(list3);//[1,1,1]

//獲取列表的第一個元素
print([1,2].first);//1 
//獲取列表中的最后一個元素
print([1,2].last);//2 
//獲取列表的長度
print([1,2].length);//2

print(["a","b","c","d"][3]);//d 
print([1,2]+[2,3]);//[1, 2, 2, 3] 
var data = [1,2,3]; 
data[2] = 4; 
print(data);//[1, 2, 4]

List 類中封裝了大量的實例方法,這些方法可以極大地提高開發者的工作效率

var l = []; 
 //向列表中增加元素
 l.add(1); 
 //向列表中增加一組元素
 l.addAll([2,3]); 
 //將列表對象映射成字典對象,下標為鍵,元素為值
 print(l.asMap());//{0: 1, 1: 2, 2: 3} 
 //將列表中某個范圍的元素進行覆蓋
 l.fillRange(0,2,"a");//[a, a, 3] 
 //獲取列表某個范圍內的元素集合
 print(l.getRange(0,3)); 
 //獲取列表中某個元素的下標,從前向后找,如果沒有,就返回-1 
 print(l.indexOf('a')); 
 //獲取列表中某個元素的下標,從后向前找,如果沒有,就返回-1 
 print(l.lastIndexOf("a"));
//向列表中的指定位置插入一個元素
 l.insert(0,'s');//[s, a, a, 3] 
 //向列表的指定位置插入一組元素
 l.insertAll(0,["a","b","c"]);//[a, b, c, s, a, a, 3] 
 //刪除列表中的指定元素,從前向后找到第一個刪除
 l.remove("a"); 
 //刪除列表中指定位置的一個元素
 l.removeAt(0); 
 //刪除列表中的最后一個元素
 l.removeLast(); 
 //刪除列表中指定范圍內的元素
 l.removeRange(0,2); 
 //將列表中指定范圍的元素進行替換,替換為集合參數中的元素
 l.replaceRange(0,2,[1,2,3,4]); 
 //截取列表中范圍內的元素返回新的列表
 print(l.sublist(0,3)); 
 //判斷列表中是否包含指定元素
 print(l.contains(2)); 
 //使用指定拼接符將列表拼接為字符串
 print(l.join("-"));//1-2-3-4 
 //將列表轉換為字符串
 print(l.toString());//[1, 2, 3, 4] 
 print(l); 
 //刪除列表中所有的元素
 l.clear();

1.2.5 字典類型

字典是一組鍵值對的集合,通過鍵可以完成對值的修改、
查找、添加或刪除。在 Dart 中,字典類型叫作 Map

//鍵為字符串類型、值為整數類型的字典
Map<String,int> map2 = {"1":1,"2":2};

//使用構造方法創建字典
var map3 = Map(); 
//新增鍵值對
map3["name"] = "琿少"; 
print(map3["name"]);//琿少
//修改鍵值
map3["name"] = "Lucy"; 
print(map3["name"]);//Lucy 
//不存在的鍵值將返回 null 
print(map3["age"]);//null 
//將某個鍵的值置為 null,并不會將此鍵值對刪除
map3["name"] = null; 
print(map3["name"]);//null

Map 對象中常用的屬性列

//判斷 Map 是否為空
print({"1":1,"2":2}.isEmpty);//false 
//判斷 Map 是否為非空
print({"1":1,"2":2}.isNotEmpty);//true 
//獲取 Map 所有的鍵
print({"name":"Lucy","age":25}.keys);//(name, age) 
//獲取 Map 所有的值
print({"name":"Lucy","age":25}.values);//(Lucy, 25) 
//獲取 Map 中鍵值對的個數
print({"name":"Lucy","age":25}.length);//2 
//獲取類型
print({"name":"Lucy"}.runtimeType);//_InternalLinkedHashMap<String, String>

Map 類中的實例方法

var map = {}; 
//向 Map 中追加鍵值對
map.addAll({"name":"Lucy","age":28});//{name: Lucy, age: 28} 
//判斷 Map 中是否包含某個鍵
print(map.containsKey("name"));//true 
//判斷 Map 中是否包含某個值
print(map.containsValue("Lucy"));//true 
//刪除某個鍵值對
map.remove("name"); 
//將 Map 轉換成字符串
print(map.toString()); 
//清空 Map 中的鍵值對
map.clear();

二、Dart中的運算符

2.1 算數運算符

算數運算符通常用來進行簡單的數據運算,例如加、減、乘、除等。

print(1+2);//3 
print("1"+"2");//12
print(3-1);//2
print(-(-1));//1
print(2*4);//8
print(10/2);//5.0
// 整除
print(9~/2);//4
// 取模運算符
print(9%2);//1

// 自加和自減
var a = 3; 
a++; 
print(a);//4 
++a; 
print(a);//5

2.2 比較運算符

比較運算符的作用是進行兩個值的比較。雖然在 Dart 中,比較運算符的操作數可以是任意類型的值,但是對于 List、Map 或 String 對象,一般會使用函數來進行比較,比較運算符更多用于數值之間的比較。可用的比較運算符如下表所示。


image.png

2.3 類型運算符

Dart 中的類型運算符有 3 種:as、is 和 is!。

as 運算符用來進行類型的“轉換”,需要注意,這里的類型轉換并不是真正意義上的轉換,其并不會真正修改數據的類型,而是告訴 Dart將當前數據當成某個類型的數據來進行處理。在面向對象開發中,這個運算符非常有用,后面我們會介紹。

is 運算符用來判斷數據是否屬于某個類型:如果屬于,就返回布爾值 true;如果不屬于,就返回布爾值 false。

is!運算符的作用則與 is 剛好相反,它用來判斷數據是否不屬于某個類型,示
例如下:

var a = 1; 
var b = "2"; 
print(a is int);//true 
print(b is! String);//false

2.4 復合運算符

簡單理解,復合運算符是多種簡單運算符的復合。復合運算符通常也叫作賦值復合運算符,因為其總是一種運算符與賦值運算符的組合。


image.png

2.5 邏輯運算符

邏輯運算符是針對布爾值進行運算的運算符。我們知道,布爾值只有兩種:true 和 false。邏輯運算符所適用的操作數也只有 true 或者 false。

“!”被稱為邏輯非運算符,進行邏輯非運算,它是一個前置運算符,且只有一個操作數,當操作數為布爾值 true 時,運算結果為布爾值 false,當操作數為布爾值 false 時,運算結果為布爾值true。

“||”被稱為邏輯或運算符,進行邏輯或運算。邏輯或運算遵守下面的運算規則:
(1)當兩個操作數中至少有一個操作數為 true 時,運算結果為 true。
(2)當兩個操作數都為 false 時,運算結果才為 false。

“&&”被稱為邏輯與運算符,進行邏輯與運算。邏輯與運算遵守下面的運算規則:
(1)當兩個操作數中至少有一個操作數為 false 時,運算結果為 false。
(2)當兩個操作數都為 true 時,運算結果為 true。

print(!false);//true 
print(!true);//false

print(false||false);//false 
print(false||true);//true 
print(true||false);//true 
print(true||true);//true

print(false&&false);//false 
print(true&&false);//false 
print(false&&true);//false 
print(true&&true);//true

2.6 位運算符

位運算符是對二進制位進行操作的運算符。在計算機中,所有的數據存儲實際上采用的都是二進制。

“&”用來進行按位與運算。所謂按位與運算,是指將兩個運算符的每一個二進制位分別進行與運算,即若兩個對應二進制位都為 1,則運算結果為 1,否則為 0。

“|”用來進行按位或運算。與按位與運算一樣,按位或運算將兩個運算數的每個二進制位分別進行或運算,若兩個對應二進制位有一個為 1,則運算結果為 1,否則運算結果為 0。

“~”用來進行按位非運算。按位非運算是一個前置的單元運算符,其只有一個操作數,對操作數的每一個二進制位進行取反,即為 0 的位運算后結果為 1,為 1 的位運算后結果為 0。

“^”用來進行按位異或運算。關于按位異或運算,只需要牢記進行運算的兩個數位相同時,運算結果為 0,否則運算結果為 1 即可,即兩個二進制位都為 0 或者都為 1 時,運算結果為 0,否則運算結果為 1。

“<<”用來進行按位左移運算,即將每一個二進制位向左移動指定位數。對于二進制數據,
一個很重要的特點是每左移一位,會使原數值進行乘 2 操作

“>>”用來進行按位右移操作

var a = 10; //二進制 1010 
var b = 3; //二進制 0010 
print(a&b);//2 即二進制 0010

var c = 10; //二進制 1010 
var d = 4; //二進制 0100
print(c|d);//14 即二進制 1110

var e = 4; //00000100 
print(~e); //11111011 以補碼表示 原碼為 00000101 且為負數 即-5

var f = 3; // 0011 
var g = 5; // 0101 
print(f^g);// 0110 十進制 6

var h = 3;//0011 
print(h<<1);//0110 十進制 6

var i = 4;//0100 
print(i>>1);// 0010 十進制 2

2.7 條件運算符

條件運算符與流程控制語句中的條件語句作用很像.

“?:”是一個三元的運算符,其有 3 個操作數,第一個操作數可以是一個布爾值或者運算結果為布爾值的表達式,
當這個操作數為 true 時,條件運算的結果為第二個操作數的值,當第一個操作數為 false 時,條件
運算的結果為第三個操作數的值。

“??”是 Dart 中的空條件運算符,其有兩個操作數,若第一個操作數為 null,則運算后的值為第二個操作數的值,若第一個操作數為非 null 值,則運算后的值為第一個操作數的值。這個運算符最大的作用是保證運算的結果不為 null 值,通常用來進行安全保證。

var a = 3; 
 var b = 5; 
 var res = a>b ? "a>b" : "a<=b"; 
 print(res);//a<=b

var c = null; 
print(c==null?"無作為":"額外操作 a:$c");

var c = 3; 
print(c??"無作為");

var c = null; 
c ??= 0;//與 c = c??0;意義完全一樣

2.8 級聯運算符

級聯運算符使用“..”表示,級聯運算符是 Dart 中比較高級的一種運算符,它可以讓開發者對某個對象連續地進行一系列操作。這樣的好處是可以減少中間變量的生成,并且讓開發者更暢快地體驗 Dart 編碼的樂趣。

var p =People()..name="琿少"..age=26; 
print("name:${p.name},age:${p.age}");

2.9 點運算符

點運算符用來對對象的屬性和方法進行操作。

class People { 
 String name; 
 int age; 
 void printSelf(){ 
 print("name:${name},age:${age}"); 
 } 
} 

main() { 
 var p = People(); 
 p.name = "琿少"; 
 p.age = 26; 
 p.printSelf();//name:琿少,age:26 
}

補充,條件成員訪問運算符“?.”。這個運算符的作用是,如果所調用的對象是非 null 值,就會正常進行訪問,否則返
回 null,但是不會產生錯誤

var c = null; 
print(c?.a);//null

3 Dart 中的流程控制語句

條件語句:if-else
循環語句:while,do-while,for,for-in
中斷語句:break,continue
多分支條件語句:if-else if-else,switch-case
異常處理:throw,try-catch-finally

補充:

while 語句會首先進行循環條件的判定,如果不滿足,
就不再執行循環體,滿足條件才會進行循環;

do-while 語句則是首先執行一次循環體中的代碼,之后進行循環條件的判定,如果滿足,就繼續執行循環體,如果不滿足,就跳出循環

break 語句會直接跳出本層循環,執行循環后面的代碼,而 continue 語句則是跳過本次循環后,還會進行循環條件的判定

3 Dart 高級進階

3.1構造方法

一旦重寫了構造方法,默認的無參構造方法將不再可用。

構造方法的實質是將對象屬性的賦值過程由外界封裝到類的內部。

構造方法的編寫還有一個小技巧,一般情況下,我們可以直接將構造方法定義成如下模樣,Dart 會自動進行參數和屬性的匹配,進行賦值,非常方便.

main() { 
    var circle = new Circle(6,1,1);//使用參數構造圓形對象
    print(circle.radius);//6.0 
} 
class Circle { 
    //半徑
    double radius = 0;
    //圓心 X 
    double centerX = 0; 
    //圓心 Y 
    double centerY = 0; 
    //構造方法
    Circle(this.radius,this.centerX,this.centerY); 
}

一個類需要有多個構造方法,比如自定義的圓形類,很多時候需要快速創建出單位圓(圓心為坐標原點、半徑為 1 的圓)。這時,就可以定義一個便捷的構造方法幫助我們直接生成單位圓,這類構造方法也被稱為命名構造方法.

main() { 
    var circle2 = Circle.standard(); 
    print(circle2.radius);//1 
} 
class Circle { 
    //半徑
    double radius = 0; 
    //圓心 X 
    double centerX = 0; 
    //圓心 Y 
    double centerY = 0; 
    //構造方法
    Circle(this.radius,this.centerX,this.centerY); 
    //命名構造方法,單位圓
    Circle.standard(){ 
        this.radius = 1; 
        this.centerX = 0; 
        this.centerY = 0; 
    } 
}

命名構造方法通常用來快速地創建標準對象,同樣,命名構造方法也可以有參數,并且只要參數名與類中定義的屬性名一致,也可以使用 Dart 自動匹配賦值的特性。

3.2實例方法

類封裝了屬性和方法,屬性用來存儲描述類的數據,方法用來描述類的行為。

方法的用法和函數一樣,只是在調用時需要用對象來調用,并且方法中會自動將當前對象綁定到 this 關鍵字上。也就是說,在方法中可以通過 this 關鍵字獲取對象的屬性信息,也可以調用其他方法。方法也需要通過點語法來進行調用。

Setters 方法與 Getters 方法
Setters 方法用來設置對象屬性,Getters 方法用來獲取對象屬性。其實當我們使用點語法訪問對象屬性信息時,調用的就是 Setters方法或 Getters 方法,在定義屬性時,Dart 會自動生成默認的 Setters 方法和 Getters 方法。Setters方法和 Getters 方法的另一大作用是定義附加屬性,附加屬性也可以理解為計算屬性,即這些數據通常不是描述對象的最原始數據,而是通過計算得來的,例如下面的description就是附加屬性:

main() { 
    var teacher = Teacher("琿少",1101,"Dart"); 
    teacher.sayHi("小明"); //Hello 小明,我是琿少老師!編號為1101 
    teacher.teaching(); //琿少老師正在進行 Dart 教學
    print(teacher.description); //琿少:Dart 
    teacher.description = "Lucy:JavaScript"; 
    teacher.teaching(); //Lucy 老師正在進行 JavaScript 教學
} 
class Teacher { 
    String name; 
    int number; 
    String subject; 
    Teacher(this.name,this.number,this.subject); 
    void sayHi(String toName){ 
       print("Hello ${toName},我是${this.name}老師!編號為${this.number}"); 
    } 
    void teaching(){ 
       print("${this.name}老師正在進行${this.subject}教學。"); 
    } 
    String get description{ 
       return "${this.name}:${this.subject}"; 
    }
    set description(String value){ 
       this.name = (value.split(":") as List)[0]; 
       this.subject = (value.split(":") as List)[1]; 
    } 
}

上面的代碼中,description 就是附加屬性,其并沒有真正占用內存空間進行存儲,而是通過其他屬性計算而來的

3.3 抽象類與抽象方法

抽象類,是面向對象開發中較為難理解的一點。在 Dart 中,抽象類中可以定義抽象方法。
抽象方法,是指只有定義卻沒有實現的方法,抽象是面向接口開發的基礎。
抽象類實際上就是一個接口,接口中定義了未實現的方法告訴調用者:如果有類實現了這個接口,這個類就擁有接口所描述的功能。例如,我們可以為教師類定義一個接口,示例如下:

abstract class TeacherInterface { 
    void teaching(); 
}

上面的 TeacherInterface 接口中只定義了一個抽象方法,Teacher 類可以對這個接口進行實現,示例代碼如下:

abstract class TeacherInterface { 
    void teaching(); 
} 
class Teacher implements TeacherInterface { 
    String name; 
    int number; 
    String subject; 
    Teacher(this.name,this.number,this.subject); 
    void sayHi(String toName){ 
        print("Hello ${toName},我是${this.name}老師!編號為${this.number}"); 
    } 
    void teaching(){ 
        print("${this.name}老師正在進行${this.subject}教學。"); 
    } 
}

一個類也可以同時實現多個接口,例如再定義一個人類接口,示例如下:

abstract class TeacherInterface {
    void teaching(); 
} 
abstract class PeopleInterface { 
    void sayHi(String name); 
} 
class Teacher implements TeacherInterface,PeopleInterface { 
    String name; 
    int number; 
    String subject; 
    Teacher(this.name,this.number,this.subject); 
    void sayHi(String toName){ 
        print("Hello ${toName},我是${this.name}老師!編號為${this.number}"); 
    } 
    void teaching(){ 
        print("${this.name}老師正在進行${this.subject}教學。"); 
    } 
}

抽象類不可以被實例化,即不能直接使用抽象類來構造實例對象,只能通過實現這個抽象類接口的類或者繼承它的子類來實例化對象。

遺留問題:類實現了抽象類,則類中必須重寫抽象類中的方法嗎?

3.4 類的繼承

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容