15-01-11 C# 物件導向 10

來源:互聯網
上載者:User

標籤:

類中的成員,如果不加存取修飾詞,預設是private;

私人的,只能在當前類的內部訪問;

理論上是給每個私人的欄位配備一個公有的屬性;

靜態函數中只能訪問靜態成員;靜態類中只能有靜態成員;非靜態函數既可以訪問靜態成員,也可以訪問非靜態成員,非靜態類中既可以有靜態成員,也可以有非靜態成員;

this的作用1.當前類的對象,是為了把欄位(屬性)和局部變數區分開來;欄位和屬性是和方法平級的,而局部變數是在方法裡面的;

namespace(命名空間),用於解決類重名問題,可以看做類的檔案夾;

命名空間裡面有很多很類;命名空間其實就是相當於項目;

如果我們要使用一個新類,但是這個新類不存在上面的命名空間裡,這個時候我們首先要引用這個類的命名空間;

類是屬於命名空間(項目)的,如果沒有引用相應的命名空間的話,我們就不能使用這個類;

如何引用類的命名空間,

1.把游標放到類的名稱下,會看到左下角有個藍色的小塊塊,游標移過來點開,就可以引用命名空間

2.把游標放到類的名稱下,alt+shift+F10;

3.把命名空間記住,直接在上面打出來;

如果在自己的兩個項目中,我要在02項目中引用01項目,

第一步,添加引用;在02的專案檔的引用裡,右鍵,添加引用,預設選的是項目,選中引用的項目,點確定,這個時候發現在02項目的引用中有了01項目;(系統內建的少了這一步)

第二步,在上面引用命名空間,

在C#中資料類型確切的分為實值型別和參考型別, 區別 1.實值型別和參考型別,在記憶體上儲存的地方不一樣,2.在傳遞實值型別和傳遞參考型別的時候,傳遞的方式不一樣,實值型別我們稱之為值傳遞,參考型別我們稱之為引用傳遞

在記憶體中我們人為了得分成了5塊,我們程式員常用的就是堆,棧,靜態儲存地區,靜態儲存地區用來儲存靜態成員,堆棧就是用來儲存我們這些資料類型的資料

實值型別:int,double,bool,char,decimal,struct,enum

參考型別:string,自訂類,數組

實值型別的值是儲存在記憶體中的棧上的,參考型別的值是儲存在記憶體的堆中,

int number = 10; 10存在棧中,棧記憶體空間的名字是number 

string s = "123"; "123"存在堆中,s在棧中,但是名字為s的棧空間中,存的是"123"在堆中的地址;

Person p = new Person(); p.Name = "張三"; new Person()存在堆中,new Person()才是一個對象,p在棧中,但是名字為p的棧空間中,存的是new Person()在堆中的地址;Name = "張三"也在堆中

實值型別的值是存在記憶體中的棧中,參考型別的值存在記憶體中的堆中,但是參考型別也在棧上開闢了空間,存的是這個值在堆中的引用(地址);

字串區別於別的類型有一個很特別的性質,叫

1.字串的不可變性, int n1 = 10; ni = 20;    在堆中的10變成了20;老值10,不存在了; string s1 = "張三"; s1 = "李四"; 當你給字串重新賦值之後,老值"張三"並沒有銷毀,而是重新開闢一塊堆空間儲存新值;此時s1在棧中的地址由原來的"張三"的地址變成了"李四"的地址;此時張三還在記憶體中 因此對字串迴圈賦值的話,會在堆記憶體中產生大量的垃圾; 當程式結束後,GC掃描整個記憶體,如果發現有的空間沒有被指向,則立即把它銷毀;

string s1 = "張三"; string s2 = "張三";    理論上在堆中有2塊空間儲存"張三",在棧中有兩塊空間s1,s2分別指向各自的"張三";但事實不是這樣的,事實上在堆中只開闢了一塊空間,叫做"張三" ,s1,s2同時都指向張三;s1,s2在堆中的地址是一樣的,在這時候s1="123" 原來的"張三"是不會變的,因為字串的不可變性,因此會在堆空間中重新開闢一塊空間儲存"123";

如何看變數在記憶體中的地址,產生運行,調試菜單,視窗,即時裡面,在即時視窗裡面輸入&變數名,斷行符號就能看到;有兩個地址,上面那個是棧中的地址,下面那個是堆中的地址

2.我們可以將字串看做是char類型的唯讀數組; 一個string類型可以看做是很多很多char類型組成,很多很多的char類型可以看做是一個數組;

唯讀意思是只可以訪問,但不可以改變;

string s = "abcdefg";既然可以把s當做一個數組來處理,那就意味著可以通過索引來訪問其中的某一個元素; Console.WriteLine(s[0]);  //成功輸出a

如果要把第一個字元a改變為b;首先要想辦法訪問到第一個字元; s[0] = ‘b‘;//報錯,因為string是char類型的唯讀數組;

如果非要將字串的第一個字元變‘b‘;

1.首先將字串轉換為char類型的數組;把它轉換為一個真正的數組,那麼既可讀,又可寫了;

char[] chs = s.ToCharArray(); chs[0] = ‘b‘;

2.將字元數組轉化為字串;

s = new string(chs);

ToCharArray()將字串轉化為char[]數組; new String(char[] chs)能夠將char[]轉化為字串;

當程式中要對字串進行大量的重新賦值,拼接等操作的時候,如果用string,在堆記憶體中會產生大量的垃圾 因此我們可以用StringBuilder這個類;

StringBuilder sb = new StringBuilder();

記錄程式啟動並執行時間,我們呢可以用StopWatch這個類;

StopWatch sw = new StopWatch();//建立一個計時器;

sw.Start();  //開始計時;

sw.Stop(); //結束計時;

sw.Elapsed 擷取測量所用的時間;

str += i;字串的追加; sb.Append(i);追加;

為什麼string追加速度這麼慢,因為它每次都要在記憶體中開闢空間;stringbuilder沒有開空間; 雖然中間用的是stringbuilder但最後還是把它轉化string, sb.ToString();

一切類型都可以通過ToString()轉化為字串類型;

str.Length;  調用字串的屬性得到字串的長度;

str.ToUpper();  將字串轉化為大寫形式;

str.ToLower();  將字串轉化為小寫形式;

str.Equals(str1,StringComparison.OrdnialIgnoreCase); 忽略大小寫比較兩個字串;

char[] chs = {‘_‘,‘+‘,‘-‘,‘*‘,‘ ‘}; 

str.split(chs,StringSplitOptions.RemoveEmptyEntries);在str裡把字元數組裡有的字元給去掉,傳回值是string[];

兩個小黃塊就是枚舉類型

str.split(new char[]{‘_‘,‘+‘,‘-‘,‘*‘,‘ ‘},StringSplitOptions.RemoveEmptyEntries); //等效的;

str.Contains("老趙");判斷字串裡有沒有老趙;

str.Replace("老趙","**"); 將字串中的老趙替換為**;

Substring和Split在字串中經常會用到這兩個方法; str.Substring(1,2); 1是要截取開始的索引,2是要截取的長度;

str.StartsWith("今天");判斷字串是不是以"今天"開始;

str.EndsWith("今天");判斷字串是不是以"今天"結尾;

str.IndexOf(‘天‘); 拿到‘天‘在字串中首次出現的索引;傳回值int; 如果找不到就返回-1;

str.IndexOf(‘天‘,2); 從第二個索引開始找天首次出現的索引,傳回值int;  如果找不到就返回-1;

str.LastIndexOf(‘天‘);找天在字串中最後一次出現的索引;

string path = @"c:\a\b\c........\射鵰英雄傳.wav";

int idndex = path.LastIndexOf("\\");

path = path.SubString(index+1);  //擷取檔案名稱;

str.Trim();//去掉字串的前面和後面的空格

str.TrimStart();//去掉字串的前面的空格

str.TrimEnd();//去掉字串的後面的空格

string.IsNullOrEmpty(str);判斷字串是不是空值或者null;

string[] str ={"張三","李四","王五","趙六","田七"};

string strNew = string.join("|",str);  //得到張三|李四|王五|趙六|田七

string strNew = string.join("|","張三","李四","王五","趙六","田七");也可以這樣寫,因為前面有params可變參數;

string在運行(賦值,拼接)的時候會產生新的執行個體,而StringBuilder不會產生新的執行個體

File類是一個靜態類;

File.ReadAllLines(path,Encoding.Default) 

//path是檔案的路徑;讀取檔案中的所有的行,傳回型別是string[];Encoding.Default用來解決亂碼;

要改變一個字串,除了重新賦值之外,可以先把它變成一個字元數組,在通過迴圈或者調用方法改變字元數組,再把這個字元數組轉化為字串;

.net類庫提供的字串方法還是很強大的;

封裝就是把一個功能寫成一個方法調用,具體這個功能怎麼實現的不必知道,就像調用.net類庫提供的方法一樣;

每寫一個類應該建立一個類檔案去寫;

public class Student:Person

{  

    private int _id;   

    public int Id   

   {     

     get{return _id;}     

     set{_id = value;}   

    }       

    public void Study()   

   { 

     Console.WriteLine("學習");  

    } 

   //public Student(string name, int age,char gender,int id)   

   //{   

   //this.Name = name;   

   //this.Age = age;   

   //this.Gender = gender;   

   //this.Id = id;   

   //  }                                      

  //這些代碼裡的大部分在父類裡已經寫過了,如果用父類無參的建構函式,一行都省不了;因此要調用父類有參的建構函式                                          

  //這樣一來,建構函式也執行了,對象也建立了,同時,三行代碼也不需要寫了。     

    public Student(string name, int age,char gender,int id)   //運行到這裡的時候,跳到父類的建構函式;   

    :base(name,age,gender)   

    {       

      this.Id = id;   

    }                                                             

    public new  void Test()    

    {       

       Console.WriteLine("測試1");    

   }

}

      public class Teacher:Person

    {   

       public Teacher(string name,ing age,char gender,int salary):base(name,age,gender)    

       {       

         this.Salary =salary;   

       }

        private int _salary;  

        public int Salary   

      {     

        get{return _salary;}   

       set{_salary = value;}   

       }

       public void Teach()   

       {      

         Console.WriteLine("教學");

       }                       

         public  new void Test()    

        {      

          Console.WriteLine("測試2");

        }   

}

 

public class Driver:Person

 {   

      private string _driveTime;   

      public string DriveTime   

      {    

         get{return _driveTime;}    

         set{_driveTime = value;}

       }

       public void Drive()   

       {     

          Console.WriteLine("開車");   

        }        

       public Driver(string name,ing age,char gender,int driveTime)

      :base(name,age,gender)   

       {     

            this.DriveTime =driveTime;  

        }

         public  new void Test()  

       {      

            Console.WriteLine("測試3");   

       }  

      }

      建構函式可以解決對象初始化時候的代碼冗餘,

     :this可以解決建構函式重載的時候的冗餘代碼;

     繼承是用來解決類與類之間的代碼冗餘;把幾個類中共重複的成員單獨的拿出來封裝成一個類,作為這幾個類的父類;

      public class Person

     {   

      private string _name;   

      public string Name   

     {     

       get{return _name;}     

       set{_name = value;}  

      }     

      private int _age;   

      public int Age   

     {     

       get{return _age;}     

       set{__age = value;}   

     }      

     private string _gender;   

     public string Gender   

     {     

        get{return _gender;}     

        set{_gender = value;}   

     }

   public void CHLSS()   

   {     

      Console.WriteLine("吃喝拉撒睡");   

    }

   public Person(string name,int age,char gender)   

    {       

      this.Name = name;       

      this.Age = age;       

       this.Gender = gender;  

     }       

     // public Person()   

    // {

    //   }

     public void Test()    

     {      

        Console.WriteLine("測試");  

      }

}

 智能提示的正方體是方法的意思;

子類既可以由父類的成員,也可以有自己的成員;

我們可能會在一些類中,寫一些重複的成員,我們可以將一些重複的成員,單獨的封裝到一個類中,作為這些類的父類

Student,Teacher,Drive  子類(衍生類別)  

Person                        父類(基類)

我們看子類在父類那裡繼承過來了什麼,就看子類對象能訪問到父類的什麼;能訪問到的表示繼承過來了;

上面那個例子,子類繼承了父類的屬性和方法;子類沒有繼承父類的私人欄位;

1.繼承的單根性,一個子類只能有一個父類;

2.繼承的傳遞性,A繼承B,B繼承C   A不僅能訪問B的成員,A也能訪問C的成員;

查看類圖:可以看出各個類的關係;右鍵項目名,視圖,查看類圖;

如果子類繼承了父類的建構函式,那麼建立子類對象的時候,應該會調用到父類的建構函式;

子類沒有繼承父類的建構函式;但是子類建立對象的時候,先會執行父類的建構函式,執行完父類的建構函式,再來執行自己的建構函式, 執行父類的建構函式就是建立了一個父類對象,

當我們建立子類對象的時候,首先會在子類的內部建立一個父類的對象出來,這樣才能用到父類的屬性和方法;不然子類對象裡面沒有父類的對象,怎麼調用父類的屬性和方法;

因此父類裡寫了一個有參的建構函式後,父類無參的建構函式就被幹掉了,就不能建立父類的對象出來了(因為子類建立對象的時候,調用的是父類無參的建構函式); 如果父類中重新寫了一個有參數的建構函式之後,那個無參的就被幹掉了,子類就調用不到了,所以子類會報錯,

解決辦法

1.在父類中重新寫一個無參數的建構函式; //一般不去這麼做;

2.在子類中顯示調用父類的建構函式,關鍵字:base()

ctrl+K+D代碼對齊;

本來子類調用的是父類無參的建構函式,現在寫了個有參的父類的建構函式,原來的無參的父類建構函式被幹掉了,因此調不到原來的無參的建構函式了, 所以去調用有參的建構函式,使用關鍵字:base();

Student s = new Student("學生",18,‘男‘,101);

Object類是所有類的基類;如果你沒有讓一個類去繼承另外一個類,那麼這個類預設就繼承於Object;

在C#中所有類都直接或者間接繼承Object類;

如果子類的成員名稱和父類的成員名稱一樣,會把從父類繼承過來的一樣名字的成員隱藏掉;隱藏的後果是調用不到父類的那個重名的成員了;  

public  new void Test()把父類中重名的成員隱藏掉了;加了new不警示告錯誤了;

new 1.建立對象 2.隱藏從父類那裡繼承過來的同名成員

隱藏的後果,子類調用不到父類的被隱藏的成員;

因此,在繼承的時候,盡量不要把子類的成員名字寫的和父類的成員名字一樣;

Object也是參考型別,因為它是類;

 

15-01-11 C# 物件導向 10

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.