TODO: 單例模式,只能創建一個物件(對象)
物件導向(面向對象)的複習
- 封裝、繼承、多型(多態)
Class類別的成員
- Class類別的成員:屬性、欄位/字段、構造函數、方法、介面/接口
- Field(欄位/字段):儲存數據,訪問修飾符應該設置為private私有的。
- 屬性:保護Field(欄位/字段),對Field的取值和賦值進行限定。
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
internal class Person
{
//field(欄位/字段)、屬性、構造函數、方法、介面/接口
private string _name; //field(欄位/字段)
public string Name //屬性,用來保護field(欄位/字段)
{
get { return _name; } //外部要取值的時候會執行get
set { _name = value; } //外部要賦值的時候會執行set
}
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
public Person() { }
public void SayHello()
{
//this在這裡代表當前類的這個對象
Console.WriteLine($"{this.Name}---{this.Age}---{this.Gender}");
}
}
new 關鍵字
new關鍵字:
- 在heap(堆積/堆)當中開闢空間
- 在開闢的空間中創建物件(對象)
- 調用物件(對象)構造函數
- 引用類型的值都是在heap(堆積/堆)當中
this
- 代表當前類的物件(對象)
- 調用自己的構造函數
1. 代表當前類的物件(對象)
1
2
3
4
5
6
7
8
9
public void SayHello()
{
//this在這裡代表當前類的這個對象
//如果這個方法裡也有個變數Name,
//string Name = "王五";
//如果沒有加this,Name就變成"王五"了,而不是屬性值的Name
Console.WriteLine($"{this.Name}---{this.Age}---{this.Gender}");
}
2. this調用自己的構造函數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//全參構造函數
public Person(string name, int age, char gender, int math, int english)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
this.Math = math;
this.English = english;
}
//在執行這個構造函數的時候,調的是自己的全參構造函數
public Person(string name, int age, char gender)
: this(name, age, gender, 0, 0) //繼承自己的構造函數
{
//有調用自己類別的全參構造函數,這三行就不用寫了
//this.Name = name;
//this.Age = age;
//this.Gender = gender;
}
base
一切類型的父類
構造函數
- 構造函數就是一個特殊的方法
- 沒有返回值
- 他是public公有的
- 名稱跟類名一樣
- 構造函數的作用是什麼?初始化物件(對象),當創建物件(對象)的時候,會調用構造函數。
1
2
3
4
class Person {
public Person() {
}
}
創建物件&初始化物件
- 寫好一個類,要使用它必須先創建它的物件(對象),除了靜態類、抽象類
- 給物件(對象)的每個屬性賦值的過程,稱之為物件(對象)的初始化
1
2
3
4
5
Person p = new Person(); //創建Person物件
//給物件(對象)的每個屬性賦值的過程,稱之為物件(對象)的初始化
p.Name = "張三";
p.Age = 10;
p.Gender = '男';
靜態成員&實體成員
- 有
static關鍵字代表靜態成員,靜態方法怎麼調用?直接類名.方法 - 沒有
static關鍵字稱之為實體成員、非靜態成員
1
2
3
4
5
6
7
//靜態成員 => 有static關鍵字
public static int count;
public static void SayHi() { }
//非靜態成員(實體成員) => 沒有static關鍵字
public int count;
public void SayHi() { }
對Field(欄位/字段)的保護方法:
- get()
- set()
- 構造函數
1.get()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private string _name; //field(欄位/字段)
public string Name //屬性,用來保護field(欄位/字段)
{
//外部要取值的時候會執行get
get { return _name; }
//外部要賦值的時候會執行set
set
{
//賦值的時候,對名字做限定
if (value != "李四") {
value = "李四";
}
_name = value;
}
}
2.set()
1
2
3
4
5
6
7
8
9
10
11
12
13
private int _age;
public int Age
{
get
{
//取值的時候,對年齡做限定
if (_age < 0 || _age > 100) {
return _age = 0;
}
return _age;
}
set { _age = value; }
}
3.構造函數
1
2
3
4
5
6
public Person(char gender) {
if (gender != '男' && gender != '女') {
gender = '男';
}
this.Gender = gender;
}
return
- 立即結束本次方法(立即離開方法)
- 在方法中返回要返回的值
return age = 0;
總結
- 封裝、繼承、多型(多態)
Class類別的成員
- Class類別的成員:屬性、欄位/字段、構造函數、方法、介面/接口
- Field(欄位/字段):儲存數據,訪問修飾符應該設置為private私有的。
- 屬性:保護Field(欄位/字段),對Field的取值和賦值進行限定。
new關鍵字
new關鍵字:
- 在heap(堆積/堆)當中開闢空間
- 在開闢的空間中創建物件(對象)
- 調用物件(對象)構造函數
引用類型的值都是在heap(堆積/堆)當中
this
- 代表當前類的物件(對象)
- 調用自己類的構造函數
base
- 一切類型的父類
- 繼承父類的構造函數
構造函數
- 構造函數就是一個特殊的方法
- 沒有返回值
- 他是public公有的
- 名稱跟類名一樣
- 構造函數的作用是什麼?初始化物件(對象),當創建物件(對象)的時候,會調用構造函數
創建物件&初始化物件
- 寫好一個類,要使用它必須先創建它的物件(對象),除了靜態類、抽象類
- 給物件(對象)的每個屬性賦值的過程,稱之為物件(對象)的初始化
靜態成員&實體成員
- 有
static關鍵字代表靜態成員,靜態方法怎麼調用?直接類名.方法 - 沒有
static關鍵字稱之為實體成員、非靜態成員
對Field(欄位/字段)的保護方法:
- get()
- set()
- 構造函數
return
- 立即結束本次方法(立即離開方法)
- 在方法中返回要返回的值
return age = 0;
繼承複習
解決代碼的冗餘,實現多形(多態),增加了代碼的擴展素,便於維護。
繼承有兩個很重要的特性:
- 單根性:
單根性指的是,一個類只能有一個父類,所以我們說,類是單繼承的, 誰是多繼承的?介面(接口),介面才能多繼承。 - 傳遞性:
子類可以使用父類的成員,一個類繼承了一個父類,繼承了屬性和方法,沒有繼承Field(欄位/字段)。
子類並沒有繼承父類的構造函數,而是會默認調用父類的那個無參數的構造函數。
子類為什麼調用父類的構造函數?
因為子類最終要使用父類的成員,父類沒有物件(對象)的話,你能訪問他的成員嗎?不能,所以子類會先在內部會先創建父類的物件(對象),當無參的構造函數沒有了,還能創建嗎?
解決這個問題有兩個辦法:
- 父類再加一個無參的構造函數
- 在子類中調用父類的構造函數,使用關鍵字base
Code-物件導向複習-程式碼
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
Person p = new Person('中'); //創建person物件
//給對象的每個屬性賦值的過程,稱之為物件(對象)的初始化
p.Name = "張三";
p.Age = -10;
//p.Gender = '中';
namespace _03_物件導向複習
{
internal class Person
{
//field(欄位/字段)、屬性、構造函數、方法、介面/接口
private string _name; //field(欄位/字段)
public string Name //屬性,用來保護field(欄位/字段)
{
//外部要取值的時候會執行get
get { return _name; }
//外部要賦值的時候會執行set
set
{
//賦值的時候,對名字做限定
if (value != "李四")
{
value = "李四";
}
_name = value;
}
}
private int _age;
public int Age
{
get
{
//取值的時候,對年齡做限定
if (_age < 0 || _age > 100)
{
return _age = 0;
}
return _age;
}
set { _age = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
private int _math;
public int Math
{
get { return _math; }
set { _math = value; }
}
private int _english;
public int English
{
get { return _english; }
set { _english = value; }
}
public Person() { }
public Person(char gender)
{
if (gender != '男' && gender != '女')
{
gender = '男';
}
this.Gender = gender;
}
//全參構造函數
public Person(string name, int age, char gender, int math, int english)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
this.Math = math;
this.English = english;
}
//在執行這個構造函數的時候,調的是自己的全參構造函數
public Person(string name, int age, char gender)
: this(name, age, gender, 0, 0)
{
//有調用自己類別的全參構造函數,這三行就不用寫了
//this.Name = name;
//this.Age = age;
//this.Gender = gender;
}
public void SayHello()
{
//this在這裡代表當前類的這個對象
Console.WriteLine($"{this.Name}---{this.Age}---{this.Gender}");
}
}
}
繼承複習
解決代碼的冗餘,實現多形(多態),增加了代碼的擴展素,便於維護。
繼承有兩個很重要的特性:
- 單根性:
單根性指的是,一個類只能有一個父類,所以我們說,類是單繼承的, 誰是多繼承的?介面(接口),介面才能多繼承。 - 傳遞性:
子類可以使用父類的成員,一個類繼承了一個父類,繼承了屬性和方法,沒有繼承Field(欄位/字段)。
子類並沒有繼承父類的構造函數,而是會默認調用父類的那個無參數的構造函數。
子類為什麼調用父類的構造函數?
因為子類最終要使用父類的成員,父類沒有物件(對象)的話,你能訪問他的成員嗎?不能,所以子類會先在內部會先創建父類的物件(對象),當無參的構造函數沒有了,還能創建嗎?
解決這個問題有兩個辦法:
- 父類再加一個無參的構造函數
- 在子類中調用父類的構造函數,使用關鍵字base
Code-繼承複習-程式碼
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
namespace 繼承
{
//把Student&Teacher相同的代碼提出來成父類
public class Person
{
public Person(string name, int age, char gender)
{
this.Name = name;
this.Age = age;
this.Gender = gender;
}
public string Name { get; set; } //自動屬性
public int Age { get; set; }
public char Gender { get; set; }
public void CHLSS()
{
}
}
//子類
public class Student : Person
{
//父類沒有無參的構造函數會報錯,
//解決這個問題有兩個方法:1.父類加上無參的構造函數
//2.在子類中調用父類的構造函數,使用關鍵字base
public Student(string name, int age, char gender, int id)
: base(name, age, gender)
{
this.ID = id;
}
public int ID { get; set; }
}
public class Teacher : Person
{
//在子類中調用父類的構造函數,使用關鍵字base
public Teacher(string name, int age, char gender, decimal salary)
: base(name, age, gender)
{
this.Salary = salary;
}
public decimal Salary { get; set; }
}
}