C#入門02:最愛紅燒肉-類

封裝

C#中類的訪問級別分爲public,protected,private,Internal和protected Internal.Internal的做用是限制訪問該類只能在當前程序集中,就是隻能在當前dll庫或當前exe程序中,意味着其餘的程序集不能從該類派生子類來實現。C#和C++的封裝區別還在於,C++使用public:來限定後面的語句都是在同一個做用域內,而C#的限定符只對當前語句有效,須要爲每一個成員和方法都聲明做用域,若是不使用顯示聲明,就使用默認的做用域。
class默認爲Internal做用域,成員和方法默認是Private做用域編程

//public表示該類能夠在任何地方被派生或調用
    //Internal表示該類只能在本程序集中被派生或調用
    //protected表示只能被子類派生或在子類中被調用
    //默認是Internal做用域,該類只能在本程序集中使用
    public class MyClass
    {
        //成員變量默認都是private,只能在本類使用,派生類或外部都不能夠訪問
        int age = 30;
        string name = "zhangsan";

        //成員方法默認也是private,不能被外部訪問,須要顯示添加public才能訪問
        public void Print()
        {
            Console.WriteLine("name = {0}, age = {1}", name, age);
        }

        //聲明static表示靜態方法,和C++相似,能夠使用類做用域訪問
        //由於是public,因此能夠在外部使用MyClass.sPrint()訪問
        static public void sPrint()
        {
            Console.WriteLine("This is static function!");
        }
    }
   
    //類的建立都使用new方法,這點和C++有很大區別
    MyClass obj = new MyClass();
    obj.Print();
    
    //訪問類的靜態public方法
    MyClass.sPrint();

繼承

多重繼承指的是一個類別能夠同時從多於一個父類繼承行爲與特徵的功能。與單一繼承相對,單一繼承指一個類別只能夠繼承自一個父類。
C# 不支持多重繼承。可是,您能夠使用接口來實現多重繼承。
C#派生類必須實現和基類一致的構造函數。
好比基類有base(int,int)這樣的構造函數,那麼在派生類中也必需要實現一樣的subclass(int,int)構造函數。ide

//接口1
    public interface PaintCost
    {
        int getCost(int area);
    }

    //接口2
    public interface CalArea
    {
        int getArea();
    }

    //基類實現
    class Shape
    {
        //基類構造函數
        protected Shape(int w, int h)
        {
            width = w;
            height = h;
        }

        //基類方法1
        public int GetWidth()
        {
            return width;
        }

        //基類方法2
        public int GetHeight()
        {
            return height;
        }

        //基類成員,聲明爲protected能夠被子類使用
        protected int width;
        protected int height;
    }

    // 派生類
    class Rectangle : Shape, PaintCost, CalArea
    {
        //子類構造函數,調用了基類的構造函數
        //必須實現和基類一致的構造函數,好比基類有base(int,int)這樣的構造函數
        //那麼在派生類中也必需要實現一樣的subclass(int,int)構造函數
        public Rectangle(int w, int h) : base(w, h)
        {
        }

        //實現接口1的方法
        public int getCost(int area)
        {
            return area * (width + height) ;
        }

        //實現接口2的方法
        public int getArea()
        {
            return (width * height);
        }
    }

    //建立派生類的對象
    Rectangle rect = new Rectangle(20, 30);

    //打印方法輸出
    Console.WriteLine("Cost={0}, Area={1}", rect.getCost(100), rect.getArea());

    //分別獲取基類引用,接口1和接口2的引用
    //這裏相似C++中的子類到基類的類型轉換:
    //C++: base* b = subclass;
    PaintCost cost = rect;
    CalArea cal = rect;
    Shape sh = rect;

    //從接口1打印
    Console.WriteLine("PaintCost.Cost={0}", cost.getCost(100));

    //從接口2打印
    Console.WriteLine("CalArea.Area={0}", cal.getArea());

    //從基類打印成員
    Console.WriteLine("Shape.width={0}, Shape.height={1}", sh.GetWidth(), sh.GetHeight());

    //也能夠使用as關鍵字來進行類型轉換
    Shape sh2 = rect as Shape;

    //基類到派生類的轉換:
    //C++:subclass* sub = dynamic_cast<base>(base);
    //if (sub != nullptr) 須要作一下判斷是否轉換成功
    Rectangle rect2 = sh as Rectangle;
    if (rect2 != null)
    {
        //須要作一下判斷,轉換失敗rect2爲空,但不會拋出異常
    }

多態

多態性意味着有多重形式。在面向對象編程範式中,多態性每每表現爲"一個接口,多個功能"。多態性能夠是靜態的或動態的。在靜態多態性中,函數的響應是在編譯時發生的。在動態多態性中,函數的響應是在運行時發生的。在編譯時,函數和對象的鏈接機制被稱爲早期綁定,也被稱爲靜態綁定。函數

靜態多態性
C# 提供了兩種技術來實現靜態多態性。分別爲:函數重載和運算符重載。
C#的函數重載和C++相似,運算符重載將在下一節專門說明。code

動態多態性
C#動態多態性是經過抽象類和虛方法實現的。
抽象類使用關鍵字abstract來聲明。
虛方法使用關鍵字virtual來聲明。
派生類中使用override來重載基類的抽象方法和虛方法。
一、抽象類
您不能建立一個抽象類的實例。 您不能在一個抽象類外部聲明一個抽象方法。 經過在類定義前面放置關鍵字 sealed,能夠將類聲明爲密封類。當一個類被聲明爲 sealed 時,它不能被繼承。抽象類不能被聲明爲 sealed。對象

//抽象類abstract
    abstract class Shape
    {
        //抽象方法abstract
        public abstract int area();
    }

    class Rectangle : Shape
    {
        //實現抽象方法override
        public override int area()
        {
            throw new NotImplementedException();
        }
    }

二、虛方法
當有一個定義在類中的函數須要在繼承類中實現時,能夠使用虛方法。虛方法是使用關鍵字 virtual 聲明的。虛方法能夠在不一樣的繼承類中有不一樣的實現。對虛方法的調用是在運行時發生的。繼承

class Shape
    {
        //基類虛方法,有本身的實現
        public virtual int area()
        {
            Console.WriteLine("父類的面積:");
            return 0;
        }
    }

    class Rectangle : Shape
    {
        //派生類重載虛方法,實現本身的訂製化功能
        public override int area()
        {
            Console.WriteLine("Rectangle 類的面積:");
            return (width * height);
        }
    }

運算符重載

class Box
    {
        // 重載 + 運算符來把兩個 Box 對象相加
        public static Box operator +(Box b, Box c)
        {
            Box box = new Box();
            box.length = b.length + c.length;
            box.breadth = b.breadth + c.breadth;
            box.height = b.height + c.height;
            return box;
        }
    }

    Box Box1 = new Box();         // 聲明 Box1,類型爲 Box
    Box Box2 = new Box();         // 聲明 Box2,類型爲 Box
    Box Box3 = new Box();         // 聲明 Box3,類型爲 Box

    // ...

    // 把兩個對象相加
    Box3 = Box1 + Box2;

    //特別說明:
    //這裏Box3能夠不用new Box()操做
    //若是有new操做,那麼上面的操做實際上是賦值操做,將Box1+Box2產生的Box對象拷貝給Box3
    //若是沒有new操做,那麼Box3其實是Box1+Box3產生的Box對象的引用類型
    //前者是新的對象產生,會花費更多時間和空間,後者更快,可是共享內存空間,若是該內存空間不會
    //被其餘地方使用,那麼沒有任何問題,若是有被其餘使用,就可能引起其餘問題。

    //常見的運算符重載
    public static Box operator +(Box b, Box c);
    public static bool operator ==(Box lhs, Box rhs);
    public static bool operator !=(Box lhs, Box rhs);
    public static bool operator <(Box lhs, Box rhs);
    public static bool operator >(Box lhs, Box rhs);
    public static bool operator <=(Box lhs, Box rhs);
    public static bool operator >=(Box lhs, Box rhs);
    public override string ToString();

接口

抽象類在某種程度上與接口相似,可是,它們大多隻是用在當只有少數方法由基類聲明由派生類實現時。接口使用 interface 關鍵字聲明,它與類的聲明相似。接口聲明默認是 public 的。
**C#僅支持單一繼承,但能夠實現多個接口。 **
接口也能夠被繼承,實現類必須實現繼承鏈上的全部接口方法接口

//接口1
    interface IParentInterface
    {
        void ParentInterfaceMethod();
    }

    //接口2繼承接口1
    interface IMyInterface : IParentInterface
    {
        void MethodToImplement();
    }

    //實現類繼承接口2,所以必須實現接口1和接口2的全部方法
    class InterfaceImplementer : IMyInterface
    {
        //實現接口1的方法
        public void ParentInterfaceMethod()
        {
            Console.WriteLine("ParentInterfaceMethod() called.");
        }

        //實現接口2的方法
        public void MethodToImplement()
        {
            Console.WriteLine("MethodToImplement() called.");
        }
    }
相關文章
相關標籤/搜索