面向對象設計原則:
1 開閉原則:對擴充開放,對修改(old Code)關閉
2 類的單一職責:每個類有且隻有一個改變它的原因
3 優先使用組合而非繼承: 避免耦合度過高
4 面向接口程式設計而非面向過程: 定義一個類的時候,先思考對外提供什麼功能,定義一個對外的接口
5 依賴倒置: 依賴抽象代碼,因為具體實作容易改變
6 接口隔離:盡量定義小而精的接口,類實作多個功能,繼承多個接口
7 裡式替換:父類可以被子類替換掉
8 迪米特法則 : 類之間資料傳遞越少越好
C#中抽象類與接口
相同點:
1.可被繼承, 不可被執行個體化,都是抽象的
不同:
1.抽象類可以繼承類或接口 接口隻能繼承接口
2.抽象成員在子類中的實作方式不同,abstract的要用override實作,interface的實作不用
3.抽象類可包含已實作的成員, 接口隻能出現抽象的成員
4.接口可以實作多繼承,抽象類隻能被單繼承,基類必須在接口之前
5.接口中的方法必須被子類實作,抽象類中的方法不用,抽象方法必須被實作
面向對象的三大特性:封裝,繼承,多态
封裝:組織代碼的過程
繼承:對概念和代碼的複用
繼承中的構造函數:構造函數不被繼承,子類建立對象的時候,先調用父類的構造函數,再調用自己的構造函數,在父類沒有無參的構造函數的時候,子類通過Base關鍵字指定調用調用哪個父類的構造函數。
多态:隐藏、重寫、重載
隐藏:在子類中使用new關鍵字實作隐藏父類的方法
重寫:父類方法不适用或者父類的抽象方法,子類中必須重寫。可以重寫的方法:虛方法、重寫方法、抽象方法。
虛方法:用virtual修飾的方法,子類中可以不重寫,抽象類和抽象方法都是用abstract修飾,抽象方法必須出現在抽象類中,子類必須重寫抽象方法。
接口
接口目的為了提高代碼的複用性我們用接口來定義行為
定義一組規範的資料結構,C#中為類提供某些功能
接口不能添加Public外的通路修飾符,接口中所有成員預設Public。接口中不能包含字段和已實作的方法。隻能包含屬性、未實作的方法、事件。
命名規範:一般接口的命名以"I"開頭
實作方式兩種:
隐式實作:通過方法名實作方法,方法前加public
顯示實作(少用):通過“接口.方法名”的形式實作。顯示實作可以避免二義性,通路顯示實作的接口要建立對應接口的類,來進行通路。
namespace 接口
{
//定義接口: 接口命名以大寫I開頭 , 後面單詞首字母大寫
//接口可以直接聲明,但是不能被new
//接口中的成員也是抽象的
interface IMyInterface
{
void Add(int i, int j);
}
//接口是抽象的概念,建立接口對象,需要聲明接口new子類
//接口可以被繼承
//實作接口的方法不需要 override
class MyClass : IMyInterface
{
public void Add(int a, int b)
{
Console.WriteLine(a + b);
}
}
//抽象類,成員可以是非抽象的
abstract class MyAbstractClass
{
public abstract void Add(int i, int j);
}
class MyClass2 : MyAbstractClass
{
public override void Add(int i ,int j)
{
Console.WriteLine(i + j);
}
}
class Program
{
static void Main(string[] args)
{
IMyInterface myInterface = new MyClass();
myInterface.Add(2, 2);
}
}
}
複制
顯式實作接口和隐式實作接口
//定義接口: 接口命名以大寫I開頭 , 後面單詞首字母大寫
//接口可以直接聲明,但是不能被new
//接口中的成員也是抽象的
interface IMyInterface
{
void Cal(int i, int j);
string Name { get; set; }
void Print();
}
interface ICal
{
void Cal(int i, int j);
}
//接口是抽象的概念,建立接口對象,需要聲明接口new子類
//接口可以被繼承
//實作接口的方法不需要 override
class MyClass : IMyInterface, ICal
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
//隐式實作接口
public void Print()
{
Console.WriteLine(Name);
}
//顯示實作接口
//想調用顯式接口,需要聲明父接口才可以調用
void IMyInterface.Cal(int i, int j)
{
Console.WriteLine(i + j);
}
void ICal.Cal(int i, int j) {
Console.WriteLine(i - j);
}
public void Cal(int a, int b)
{
Console.WriteLine(a * b);
}
}
複制
Struct 結構體
我們要複用一些資料時可以使用結構體來直接定義資料的集合
泛型
将類型作為參數,在使用的時候再具體決定
泛型參數可以是多個,一般使用大寫的T開頭
檢討參數一般可以使用在方法 類 委托等
namespace 泛型
{
class Program
{
static void Main(string[] args)
{
//泛型 C#2.0 推出的一種新機制 , 簡化 面向對象開發代碼
//棧
MyStack<int> myStack = new MyStack<int>();
myStack.Push(233);
myStack.Push(1);
Console.WriteLine(myStack.Pop());
Console.WriteLine(myStack.Pop());
}
}
class MyStack<T>
{
static int cap = 4;
T[] intStack = new T[cap];
static int currentIndex = 0;
public T Pop()
{
currentIndex--;
return intStack[currentIndex];
}
public void Push(T i)
{
if(currentIndex >= intStack.Length)
{
cap *= 2;
T[] newStack = new T[cap];
for(int j = intStack.Length; j < intStack.Length; j++)
{
newStack[j] = intStack[j];
}
intStack = newStack;
}
intStack[currentIndex] = i;
currentIndex ++;
}
}
}
複制
第二種寫法
//類型: 不安全的棧 會有拆裝箱操作
class MyStack2 {
public void Push<T>(T t) { }
}
複制
進行泛型限制:
限制條件為接口是,将泛型參數類型為接口或者接口的實作類
MyStack2 xixi = new MyStack2();
xixi.Push<SubCard>(new SubCard());
}
}
class Card
{
}
class SubCard : Card
{
}
//類型: 不安全的棧 會有拆裝箱操作
class MyStack2 {
//将T限制為某一類型,或其子類型
public void Push<T>(T t) where T:Card
{ }
}
複制
使用接口作為泛型限制的執行個體
對任意可比較類型資料進行升序排序(冒泡)
class MyClass02 : IComparable
{
public int i;
public int CompareTo(object obj)
{
return i.CompareTo((obj as MyClass02).i);
}
}
//對任意可比較類型資料進行升序排序
class MyClass01
{
public T[] ArraySort<T>(T[] t) where T : IComparable
{
if (t.Length > 1)
{
for (int n = 0; n < t.Length; n++)
{
for (int m = 0; m < t.Length - n - 1; m++)
{
//如果前者大于後者
if (t[m].CompareTo(t[m + 1]) >= 0)
{
T temp = t[m + 1];
t[m + 1] = t[m];
t[m] = temp;
}
}
}
}
return t;
}
}
class Program
{
static void Main(string[] args)
{
MyClass02[] c1 = new MyClass02[3];
c1[0] = new MyClass02();
c1[0].i = 11110;
c1[1] = new MyClass02();
c1[1].i = 230;
c1[2] = new MyClass02();
c1[2].i = 10;
MyClass01 c3 = new MyClass01();
c1 = c3.ArraySort<MyClass02>(c1);
Console.WriteLine(c1[0].i);
Console.WriteLine(c1[1].i);
Console.WriteLine(c1[2].i);
}
}
複制
泛型限制
1.引用類型限制
where T:class
引用類型用class表示限制,限制必須為一個類,可以是接口interface
2.值類型限制
where T:struct
int、char類型都是struct
3.構造函數類型限制
where T:new()
指定類型T必須有構造函數
4.轉換類型限制
就是我們可以通過裝箱或者強制類型轉換成目标類型的 類型都可以用于類型參數傳入。