天天看點

繼承和多态



sealed關鍵字

如果我們将類标記為sealed,編譯器将不會允許我們從這個類型派生。(c#結構總是隐式密封的。是以,我們永遠不可以從結構繼承結構,從類繼承結構或從結構繼承類。結構隻能用于模組化獨立的、使用者定義的資料類型。如果希望是is-a關系,就必須使用類。)

使用base關鍵字控制基類的建立

protected關鍵字

派生類型不再需要使用公共方法或屬性來間接通路資料了。當然,可能的壞處在于:如果派生類型有權直接通路其父類内部資料,有可能會偶爾繞過公共屬性内設定的既有業務規則。當定義受保護成員時,也就建立了一種父類和子類之間的信任級别,編譯器不會捕獲任何違背類型業務規則的異常。

包含/委托程式設計

class benefitpackage

{

   public  double  computepaydeduction()

   {  return 125.0;  }

}

partial class employee

    protected benefitpackage  empbenefits=new benefitpackage();

    public double getbenefitcost()

    {   return empbenefits.computepaydeduction();  }

    public benefitpackage benefits

    {   get { return empbenefits;  }

        set { empbenefits=value;  }

    }

    .......

嵌套類型

public class outerclass

     //公共嵌套類型可以被任何人使用

     public class publicinnerclass { }

     //私有嵌套類型隻可以被包含類的成員使用

     public class privateinnerclass { }

嵌套類型的特征:

通過嵌套類型可以完全控制内部類型的通路級别,也就是可以聲明為私有的(回憶一下,非嵌套類不能使用private關鍵字來聲明)。

由于嵌套類型是包含類的成員,是以它可以通路包含類的私有成員。

通常,嵌套類型隻用做外部類的輔助方法,而不是外部世界所準備的。

//employee嵌套benefitpackage

public partial class employee

    // benefitpackage嵌套benefitpackagelevel

    public class benefitpackage

    {

        public enum benefitpackagelevel

        {   standard,gold,platinum  }

     }

     public double computepaydeduction()

     {  return 125.0  }

在這種嵌套關系裡需要注意如何使用枚舉:

employee.benefitpackage.benefitpackagelevel mybenefitlevel=employee.benefitpackage.benefitpackagelevel.platinum;

virtual和override關鍵字

多态為子類提供了一種方式,使其可以定義為由其基類定義的方法,這種過程叫做方法重寫。

     poblic virtual void givebonus(float amount)

     {  pay+=amount ; }

......

用virtual關鍵字标記的方法成為虛方法。

如果子類希望改變虛方法的實作細節,就必須使用override關鍵字。

class salesperson:employee

{ .......

//銷售人員的獎金受銷量的影響

     public override void givebonus(float amount)

     {

            int salesbonus=0;

            if(numberofsales>=0&&numberofsales<=100)

                  salesbonus=10;

            else

             {  if(numberofsales>=101&&numberofsales<=200)

                    salesbonus=15;

                else

                    salesbonus=20;

             }

             base.givebonus(amount*salesbonus);

      }

class manager:employee

     public override void givebonus(float amout)

     {    base.givebonus(amount);

           random r=new random();

           numberofoptions+=r.next(500);

密封虛成員

{  ........

   public override sealed void givebonus(float amount)

   {  .......  }

sealed class ptsalesperson:salesperson

     public ptsalesperson(string fullname,int age,int empid,float currpay,string ssn,int numbofsales)

          :base(fullname,age,empid,currpay,ssn,numbofsales)

           {  }

     // 編譯器錯誤!不能在ptsalesperson類中重寫這個方法,因為它是被密封的

     {   }

抽象類

由于很多基類都是比較模糊的屍體,好的設計師會防止在代碼中直接建立新的employee對象。

abstract partial class employee

{   ........  }

建構多态接口

成員投影

基類/派生類的轉換規則

as關鍵字

//我們不能強制轉換frank為hexagon,但編譯沒問題

hexagon hex=(hexagon)frank;

//使用“as”來測試相容性

hexagon hex2=frank as hexagon;

if(hex2==null)

     console.writeline("sorry,frank is not a hexagon...");

is關鍵字

除了is關鍵字,c#語言還提供了is關鍵字來測試兩個項是否相容。然而,和as關鍵字不同的是,如果類型不相容,is關鍵字就傳回false而不是null引用。

超級父類:system.object

system.object的核心成員

equals() 預設情況下,如果被比較的項指向記憶體中同一個項,則方法會傳回true。是以,equals()用于比較對象引用,而不是對象的狀态。一般情況下,這個方法被重寫為:如果被比較的對象有相同的内部狀态值(也就是基于值的語義),則傳回true。要知道,如果重寫equals(),則還需要重寫gethashcode(),因為這些方法在内部用于hashtable類型從容器讀取子對象。valuetype類為所有結構重寫了該方法,它們進行的比較是基于值的。

finalize() 這個方法(在重寫後)在對象銷毀之前被調用來釋放所配置設定的資源。

gethashcode() 這個方法傳回int來辨別指定的對象執行個體。

tostring() 這個方法是用<namespace>,<type name>格式(叫做完全限定名)傳回對象的字元串表示。這個方法可以被子類重寫來傳回名稱/值對的辨別字元串以表示對象的内部狀态,而不是它的完全限定名。

gettype() 這個方法傳回type對象,它完整描述目前指向的對象。簡而言之,這是所有對象都可用的運作時類型辨別方法。

memberwiseclone() 這個方法的作用是逐個成員地傳回目前對象的副本,通常用于克隆對象。