二.面向對象
包括:對象、類、封裝、繼承、多態、屬性、索引器、接口、泛型
1.類與對象
類:用高級程序語言實現的一個ADT描述
對象:通過類聲明的常量
2.封裝
封裝的定義
把類的內部隱藏起來以防止外部看到內部的實現過程
抽象和封裝是面向對象程序設計的相關特性。抽象允許相關信息可視化,封裝則使開發者實現所需級別的抽象。
封裝的實現
C# 封裝根據具體的需要,設置使用者的訪問權限,並通過 訪問修飾符 來實現。
一個 訪問修飾符 定義了一個類成員的範圍和可見性。
- 對類中數據(Data)和操作(operation)的限制修飾符:
- private:對象本身在對象內部可以訪問(默認);
- protected:只有該類對象及其子類對象可以訪問
- public:所有對象(類的內部外部)都可以訪問;
- internal:同一個程序集(項目)的內部訪問,相當於public;
- 對類的限制修飾符:
- public:都可以使用
- internal:在同一程序集(項目) 內部使用(默認)
類成員封裝類型未定義時,默認爲private
封裝的表示
- 類圖
例:根據下列類圖實現Animal類型
public class Animal
{
public int Age;
public double Weight;
public void Eat()
{
Console.WriteLine("Animal Eat")
}
public void Sleep
{
Console.WriteLine("Animal Sleep")
}
}
3.繼承
3.1 繼承的概念
子類擁有父類的某些Data和Operation的過程
3.2 繼承的實現
- public class Child:Paren{…}
- Child:子類(派生類),Parent:父類(基類)
- 在類的聲明中,利用“:”表示繼承
- C#只支持單繼承,不允許多繼承
- public sealed class Name
- 利用sealed關鍵字可防止所聲明的類被繼承
- 父類 public protected private internal
- 子類 public protected 無法繼承 internal
3.3 子類怎樣訪問父類成員
利用base關鍵字
- 例:子類訪問父類且父類構造函數不帶參數
- 例 子類訪問父類且父類構造函數帶參數
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封裝
{
class Program
{
static void Main(string[] args)
{
Class2 class2=new Class2();
Console.WriteLine(class2.data3);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封裝
{
public class Class1
{
private int data1;//只能被類的內部訪問
protected int data2;//能被子類訪問和繼承
public int data3;//能被子類訪問和繼承
//構造函數具有形參
public Class1(int dt1, int dt2, int dt3)
{
data1 = dt1;
data2 = dt2;
data3 = dt3;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 封裝
{
public class Class2:Class1
{
//繼承時候因父類構造函數具有形參,需提供base(形參)
//或者 public class Class2(int x,int y,int z):base(x,y,z)
public Class2():base(0,2,3)
{ ;
}
}
}
3.4 怎樣表示
- 通過類圖來表示
例:根據類圖實現程序代碼,注意類之間的繼承關係
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Animal
{
public int Age;
public float Weight();
public void Eat()
{
Console.WriteLine("Animal Eat");
}
public void Sleep()
{
Console.WriteLine("Animal Sleep");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Dog:Animal
{
public void Run()
{
Console.WriteLine("Dog Run");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Bird:Animal
{
public void Fly()
{
Console.WriteLine("Bird Fly");
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Fish:Animal
{
public void Swim()
{
Console.WriteLine("Fish swim");
}
}
}
3.5實例化
爲對象分配存儲空間的過程
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Animal al = new Animal(); // 實例化Animal
al.Eat();
al.Sleep();
Dog dg = new Dog(); // 實例化Dog
dg.Age = 2;
dg.Weight = 4.5;
dg.Sleep();//繼承下來的
dg.Eat();//繼承下來的
dg.Run();
}
}
}
- 子類與父類有重名方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[]args)
{
Animal al = new Animal(); // 子類可以實例化父類
al.Eat();//重名方法存在問題
al.Sleep();
Dog dg = new Dog(); // 強制類型轉換或Dog dg =(Dog)al;
dg.Age = 2;
dg.Weight = 4.5;
dg.Sleep();
dg.Eat();
dg.Run();
}
}
}
4.多態
4.1 什麼是多態
相同的操作,對於不同的對象,可以有不同的解釋,產生不同的執行結果
4.2 多態的分類
- 運行時多態:在運行時決定執行哪個類的哪個方法(override覆寫)
處理子類父類運行方法時出現重名的情況,運行哪個方法 - 編譯時多態:在編譯時決定執行類的哪個方法(overload重載)
同一個類的內部會產生編譯時多態,方法的重載,運算符的重載
4.3 多態的實現
- 運行時多態:
- 在父類中定義並實現虛方法(virtural)
- 在子類中覆寫(override)該虛方法
- 虛方法必須有方法體,和abstract進行區分
- 覆寫虛方法,要求方法名,形參,返回值類型必須相同
例 :通過類圖實現運行時多態
- 編譯時多態
- 類中定義的方法或操作符可能有不同的版本
- 操作符的重載:operator 關鍵字
-
- public static 類型(返回值類型) operator 運算符(形參類型){…}
- 方法的重載:必須有相同的方法名、必須有不同的參數列表、可以有相同的返回值類型
例:通過類圖實現編譯時多態的代碼
4.4抽象方法與抽象類
- 抽象方法:可以看成沒有實現體的虛方法(abstract),即只有方法的聲明,需要在子類中覆寫(override)該方法
- 抽象類:含有抽象方法的類。抽象類不可以直接實例化對象
- 例:通過類圖實現抽象類及其實現的代碼
類圖中的方法名稱斜體表示此爲虛方法(abstract)
因爲含有抽象方法應該註明爲抽象類
在子類中覆寫抽象方法
- 例:飼養系統
方案一:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Raiser rar = new Raiser();
rar.RaiseBird();
rar.RaiseDog();
rar.RaiseFish();
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Dog
{
public void Run()
{
Console.WriteLine("Dog
Run");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Bird
{
public void Fly()
{
Console.WriteLine("Bird
Fly");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
public class Fish
{
public void Swim()
{
Console.WriteLine("Fish
swim");
}
public void Eat()
{
Console.WriteLine("Dog
Eat");
}
public void Sleep()
{
Console.WriteLine("Dog
Sleep");
}
}
}
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Animal2
{
class Raiser
{
public void
RaiseDog()
{
Dog dog = new Dog();
dog.Eat();
dog.Sleep();
}
public void
RaiseFish()
{
Fish fish=new Fish();
fish.Eat();
fish.Sleep();
}
public void
RaiseBird()
{
Bird bird = new Bird();
bird.Eat();
bird.Sleep();
}
}
}
- 方案2:
namespace Animal2
{
class Program
{
static void Main(string[] args)
{
Raiser rar = new Raiser();
rar.Raise(AnimalType.Dog);
rar.Raise(AnimalType.Fish);
rar.Raise(AnimalType.Bird);
}
}
}
namespace Animal2
{
public enum AnimalType { Dog,Bird,Fish };
public class Raiser
{
public void Raise(AnimalType alt)
{
switch (alt)
{
case AnimalType.Bird:
Bird bird = new Bird();
bird.Sleep();
bird.Eat();
break;
case AnimalType.Dog:
Dog dog=new Dog();
dog.Sleep();
dog.Eat();
break;
case AnimalType.Fish:
Fish fish=new Fish();
fish.Sleep();
fish.Eat();
break;
}
}
}
}
- 方案三