物件是 C# OOP 程式的基本構建塊。 物件是資料和方法的組合。 資料和方法稱為物件的成員。 在 OOP 程式中,我們建立物件。 這些物件透過方法進行通訊。 每個物件都可以接收訊息,傳送訊息和處理資料。
建立物件有兩個步驟。 首先,我們定義一個類。 類是物件的模板。 它是一個藍圖,描述了類物件共享的狀態和行為。 一個類可以用來建立許多物件。 在執行時從類建立的物件稱為該特定類的例項。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Program.
using System;
namespace Being
{
class Being {}
class Program
{
static void Main(string[] args)
{
var b = new Being();
Console.WriteLine(b);
}
}
}
在第一個示例中,我們建立一個簡單的物件。
class Being {}
這是一個簡單的類定義。 模板的主體為空。 它沒有任何資料或方法。
var b = new Being();
我們建立Being
類的新例項。 為此,我們使用了new
關鍵字。 b
變數是建立物件的控制代碼。
Console.WriteLine(b);
我們將物件列印到控制檯以獲取該物件的一些基本描述。 列印物件是什麼意思? 實際上,當我們列印物件時,我們將其稱為ToString()
方法。 但是我們還沒有定義任何方法。 這是因為建立的每個物件都繼承自基本object
。 它具有一些基本功能,可以在所有建立的物件之間共享。 其中之一是ToString()
方法。
1 2
$ dotnet run Being.Being
我們得到物件類名。
C# 物件屬性
物件屬性是捆綁在類例項中的資料。 物件屬性稱為例項變數或成員欄位。 例項變數是在類中定義的變數,該類中的每個物件都有一個單獨的副本。
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
Program.
using System;
namespace ObjectAttributes
{
class Person
{
//例項變數,這個變數必須透過類例項化後才能操作
public string name;
}
class Program
{
static void Main(string[] args)
{
var p1 = new Person();
p1.name = "Jane";
var p2 = new Person();
p2.name = "Beky";
Console.WriteLine(p1.name);
Console.WriteLine(p2.name);
}
}
}
在上面的 C# 程式碼中,我們有一個帶有一個成員欄位的Person
類。
1
2
3
4
class Person
{
public string name;
}
我們宣告一個名稱成員欄位。 public
關鍵字指定可以在類塊之外訪問成員欄位。
1
2
var p1 = new Person();
p1.name = "Jane";
我們建立Person
類的例項,並將名稱變數設定為“ Jane”。 我們使用點運算子來訪問物件的屬性。
1
2
var p2 = new Person();
p2.name = "Beky";
我們建立Person
類的另一個例項。 在這裡,我們將變數設定為“ Beky”。
1 2
Console.WriteLine(p1.name); Console.WriteLine(p2.name);
我們將變數的內容列印到控制檯。
1 2 3
$ dotnet run Jane Beky
我們看到了程式的輸出。 Person
類的每個例項都有一個單獨的名稱成員欄位副本。
C# 方法
方法是在類主體內定義的函式。 它們用於透過物件的屬性執行操作。 方法將模組化帶入我們的程式。
在 OOP 正規化的封裝概念中,方法至關重要。 例如,我們的AccessDatabase
類中可能有一個Connect()
方法。 我們無需知道方法Connect()
如何精確地連線到資料庫。 我們只需要知道它用於連線資料庫。 這對於劃分程式設計中的職責至關重要,尤其是在大型應用中。
物件將狀態/特性和行為分組,方法代表物件的行為部分。
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
Program.
using System;
namespace Methods
{
class Circle
{
private int radius;
public void SetRadius(int radius)
{
this.radius = radius;
}
public double Area()
{
return this.radius * this.radius * Math.PI;
}
}
class Program
{
static void Main(string[] args)
{
var c = new Circle();
c.SetRadius(5);
Console.WriteLine(c.Area());
}
}
}
在程式碼示例中,我們有一個 Circle 類。 我們定義了兩種方法。
private int radius;
我們只有一個成員欄位。 它是圓的半徑。 private
關鍵字是訪問說明符。 它表明變數僅限於外部世界。 如果要從外部修改此變數,則必須使用公共可用的SetRadius()
方法。 這樣我們可以保護我們的資料。
1
2
3
4
public void SetRadius(int radius)
{
this.radius = radius;
}
這是SetRadius()
方法。 this
變數是一個特殊變數,我們用它來訪問方法中的成員欄位。 this.radius
是例項變數,而半徑是區域性變數,僅在SetRadius()
方法內部有效。
1
2
var c = new Circle();
c.SetRadius(5);
我們建立Circle
類的例項,並透過在圓物件上呼叫SetRadius()
方法來設定其半徑。 我們使用點運算子來呼叫該方法。
1
2
3
4
public double Area()
{
return this.radius * this.radius * Math.PI;
}
Area()
方法返回圓的面積。 Math.PI
是內建常數。
1
2
$ dotnet run
78.5398163397448
執行該示例可得出此結果。
C# 訪問修飾符
訪問修飾符設定方法和成員欄位的可見性。 C# 具有四個基本訪問修飾符:public
,protected
,private
和internal
。 可以從任何地方訪問public
成員。 protected
成員只能在類本身內部以及繼承的和父類訪問。 private
成員僅限於包含型別,例如 僅在其類或介面內。 可以從同一程式集(exe 或 DLL)中訪問internal
成員。
修飾符還有兩種組合:protected internal
和private protected
。 protected internal
型別或成員可以由宣告它的程式集中的任何程式碼訪問,也可以從另一個程式集中的派生類中訪問。 private protected
型別或成員只能在其宣告程式集中透過同一個類或從該類派生的型別的程式碼進行訪問。
訪問修飾符可防止意外修改資料。 它們使程式更強大。
類 | 當前程式集 | 派生類 | 當前程式集中的派生類 | 整個程式 | |
---|---|---|---|---|---|
public |
+ | + | + | + | + |
protected |
+ | o | + | + | o |
internal |
+ | + | o | o | o |
private |
+ | o | o | o | o |
protected internal |
+ | + | + | + | o |
private protected |
+ | o | o | + | o |
上表總結了 C# 訪問修飾符(+是可訪問的,o 是不可訪問的)。
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
Program.
using System;
namespace AccessModifiers
{
class Person
{
public string name;
private int age;
public int GetAge()
{
return this.age;
}
public void SetAge(int age)
{
this.age = age;
}
}
class Program
{
static void Main(string[] args)
{
var p = new Person();
p.name = "Jane";
p.SetAge(17);
Console.WriteLine("{0} is {1} years old",
p.name, p.GetAge());
}
}
}
在上面的程式中,我們有兩個成員欄位。 一個被宣佈為公開,另一個被宣佈為私有。
1
2
3
4
public int GetAge()
{
return this.age;
}
如果成員欄位是private
,則訪問它的唯一方法是透過方法。 如果要在類外部修改屬性,則必須將方法宣告為public
。 這是資料保護的重要方面。
1
2
3
4
public void SetAge(int age)
{
this.age = age;
}
SetAge()
方法使我們能夠從類定義之外更改private
年齡變數。
1
2
var p = new Person();
p.name = "Jane";
我們建立Person
類的新例項。 因為名稱屬性是public
,所以我們可以直接訪問它。 但是,不建議這樣做。
p.SetAge(17);
SetAge()
方法修改年齡成員欄位。 由於已宣告private
,因此無法直接訪問或修改。
1
2
Console.WriteLine("{0} is {1} years old",
p.name, p.GetAge());
最後,我們訪問兩個成員以構建一個字串。
1
2
$ dotnet run
Jane is 17 years old
執行示例將給出此輸出。
具有private
訪問修飾符的成員欄位不被派生類繼承。
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
Program.
using System;
namespace Protected
{
class Base
{
public string name = "Base";
protected int id = 5323;
private bool isDefined = true;
}
class Derived : Base
{
public void info()
{
Console.WriteLine("This is Derived class");
Console.WriteLine("Members inherited");
Console.WriteLine(this.name);
Console.WriteLine(this.id);
// Console.WriteLine(this.isDefined);
}
}
class Program
{
static void Main(string[] args)
{
var derived = new Derived();
derived.info();
}
}
}
在前面的程式中,我們有一個Derived
類,該類繼承自Base
類。 Base
類具有三個成員欄位。 全部具有不同的訪問修飾符。 isDefined 成員不繼承。 private
修飾符可以防止這種情況。
class Derived : Base
類Derived
繼承自Base
類。 要從另一個類繼承,我們使用冒號(:)運算子。
1
2
3
Console.WriteLine(this.name);
Console.WriteLine(this.id);
// Console.WriteLine(this.isDefined);
public
和protected
成員由Derived
類繼承。 可以訪問它們。 private
成員未繼承。 訪問成員欄位的行被註釋。 如果我們取消註釋該行,則程式碼將無法編譯。
1
2
3
4
5
6
7
$ dotnet run
Program.(9,22): warning 0414: The field 'Base.isDefined' is assigned but its value
is never used [C:\Users\Jano\Documents\harp\tutorial\oop\Protected\Protected.proj]
This is Derived class
Members inherited
Base
5323
執行程式,我們收到此輸出。