跳到主要內容

C#教材(7) 繼承與介面

繼承

  繼承是物件導向一個很重要的特性,我們可以想像它是一種階層式的關係,如下所建,子類別(Child Class)會繼承父類別(Parent Class)所擁有的方法(Method)與屬性(Property)。例如: 父類別為筆,筆的屬性有名稱、價錢、外型和顏色。當我們要生產毛筆時,我們可以繼承這個父類別加入子類別自我的屬性:



  • 繼承的優點 : 

1.容易達成軟體再利用(Software reuse),並減少相同功能的重覆開發。
2.可透過繼承的方式來擴充原有類別的功能。



繼承語法
  class subClass : parentClass{
            // program            
  }



繼承的限制
  1. 子類別只可以繼承一個父類別
  2.  父類別繼承最上層的System.Object
  3.  子類別一定會呼叫父類別的建構子(如果沒有指定呼叫的建構子,會呼叫預設的建構子)
  4.  
<parentClass>
class parentClass{
        public parentClass(string name)
        {
            //建構子
        }
}


class subClass : parentClass{
        public subClass(string name) : base(name)  // call parent constructor
        {
       
        }
}


class subClass2 : parentClass{
        public subClass2 (string name)  //沒有指定呼叫建構子,預定會呼叫有預設的建構子
        {
         
        }
}



例子: 假設動物類別(animal)為所有的生物的父類別,底下有兩個子類別分別為鳥(bird)和狗(dog)
          現在我們


class Animal{
        public String skill ;
        public String attribute;
     
         //建構子
        public Animal()
        {
         }

         //建構子
         public Animal( string skill , string attribute)
        {
              this.skill = skill ;
              this.attribute = attribute;
         }
}


class Bird: Animal{
        public Bird(string skill , string attribute) : base(skill , attribute)
        {
           
        }
}


class Dog: Animal{
          public Dog string skill , string attribute) : base(skill , attribute)
        {
         
        }
}




  • 檢查運算子 : is 運算子、as運算子或是轉型


      1.is運算子


      2.as運算子:
                        用來檢查物件是否為該類別所有,檢查可以就指派給它,不可以就給它null。
           
          Ex:  Animal animal = new Animal() ;    
                Dog myDog = animal  as Animal() ; //OK 將myDog 指定為Animal()

      3.



  • 宣告虛擬方法

我們知道子類別可以定義自己的方法,但是如果當我們規劃子類別的方法與父類別重複時,你要如何解決,在C#程式語言中,會預先在父類別定義virtual的方法,子類別利用override關鍵字來覆蓋或是替代之前的方法。

規則:

  • private修飾詞不可以覆蓋
  • 覆蓋時,名稱、參數與傳回值應該相同
  • 使用的修飾詞也要相同,當父類別使用public時,子類別也要使用public。
  • 沒有利用override關鍵字來覆蓋會出現警告,但是可以利用new來使編譯器略過

EX:

class Animal{
        public String skill ;
        public String attribute;
     
         //建構子
        public Animal()
        {
         }

       public virtual string GetSkill()
       {
         
      }
}


class Bird: Animal{

        public override string GetSkill()  //覆蓋子類別的方法
       {
         
       }

}

介面


  • 定義介面

  介面是一個很抽象的類別,但是良好的系統設計都會利用介面來完成特定的工作,它很像一個契約,實作它的人必須要造它的規定實作該介面。主要是規劃如何做和做甚麼兩個目標。在系統規劃上也可以是用來定義不同種類的物件中,針對某種特性,所需要具備的相同功能

宣告介面:


          interface IComparable{

                  int CompareTo(object obj) ;   //介面方法
          }

介面的限制:


  • 介面不能定義任何欄位,靜態也不可以
  • 介面沒有建構子/解建構子
  • 介面的修飾詞只有為public,不能用private或是其他
  • 介面只可以繼承介面。


實作介面
   class Compared : IComparable {
        //實作介面方法
        int IComparable.CompareTo(){
     
          }

    }
   

實作多介面

   class Compared : IComparable,IBound {
        //實作介面方法
        int IComparable.CompareTo(){
     
          }

    }



  • 密封類別(sealed class)

密封類別用來限制父類別不可以被子類別繼承,這種好處主要是限制類別繼承的深度,

Ex:
    //宣告密封類別
    sealed class SealedClass
    {
        public const double PI = 3.1415F;
        public void work()
        {
            Console.WriteLine("密封類別不可以work繼承");
        }


    }

Ex: 繼承SealedClass,在編譯時會出現錯誤。
    class SubSealedClass :SealedClass
    {

    }







  • 抽象類別(Abstract class)

  當我們建造房子之前須要先去做藍圖的規劃,抽象類別通常是指一個想法或是架構,
  但未有實體的建造規格。當我們需要規劃一些共同抽象行為或是屬性,通常我們會先去
  規畫一個樣板(template)然後再由其他的子類別去override這些行為

  Ex:
   //制定房子的架構
    abstract class HourseTemplate
    {
        private string _hourseType;

        public string HourseType
        {
            get { return _hourseType; }
            set { _hourseType = value; }
        }

        abstract protected void Length(double l); //長度
        abstract protected void Width(double w);  //寬度
        abstract protected void Heigh(double h);  //高度
        abstract public double Volume();          //體積
        abstract protected void Condition(string condition);
     
    }


  class Department:HourseTemplate
    {
        private double w;
        private double l;
        private double h;
        private string condition;

        public Department(double length, double width, double heigh)
        {
            Length(length);
            Width(width);
            Heigh(heigh);
        }

        protected override void Length(double l)
        {
            this.l = l;
        }

        protected override void Width(double w)
        {
            this.w = w;
        }

        protected override void Heigh(double h)
        {
            this.h = h;
        }

        public override double Volume()
        {
            return this.l * this.w * this.h;
        }


        protected override void Condition(string condition)
        {
            throw new NotImplementedException();
        }
    }

 class Codominiun:HourseTemplate
    {
        private double w;
        private double l;
        private double h;
        private string condition;

        protected override void Length(double l)
        {
            this.l = l;
        }

        protected override void Width(double w)
        {
            this.w = w;
        }

        protected override void Heigh(double h)
        {
            this.h = h;
        }

        protected override void Condition(string condition)
        {
            this.condition = condition;
        }

        //自訂方法
        public double Area()
        {
            return this.l * this.w ;
        }

        public override double Volume()
        {
            return this.l * this.w * this.h;
        }
    }

        TestHourse.cs主程式

        public static void Main()
        {
            Department department = new Department(50,50,1000);
            department.HourseType = "大樓" ;
            Console.WriteLine("{0}:{1}", department.HourseType, department.Volume());  
        }



























留言

這個網誌中的熱門文章

JavaBean 和POJO

前言 今天介紹JavaBean和POJO的不同,這兩個名詞在JAVA文章常常被拿來使用以及討論。在JDK1.1時候釋出才有的一個標準架構,很多時候常常被搞混,所以我們特別開闢一章來加以討論。POJO規範在企業級應用已經廣大的被使用的規範。 解釋 POJO : 全名為Plain-old-Java-object,只需要繼承Object就可以,沒有特定規定,只要建立的類別有setter/getter方法都可以稱為POJO JavaBean: JavaBean通常用來封裝多個物件成為單獨物件使用,規範比較嚴格,規則如下 規則 說明 1 需要實作序列(Serializable/Externalizable) 2 不能有參數的建構子( no-arg constructor) 3 需要有公用setter/getter 4 屬性必須要私人(private) 5 屬於特定POJO規則 比較 所有的JavaBean都為POJO,但是所有的POJO不一定為JavaBean 都可以當作重複元件 都必須序列化 特性都為可用性、易用性和持久化使用 - 應用 由圖我們可以知道POJO在應用程式中,主要用來存取資料庫資料達到持久化的目的,並提供給商業邏輯流程處理使用。這種POJO的架構提供程式人員開發時的可以很有規則將資料封裝並加以使用。 範例1. JavaBean(以員工為實例) JavaBean建立員工物件,可以發現Employee物件建構子沒有任何參數,屬性為私有化並setter/getter的命名方式。 //實作序列化 public class Employee implements java.io.Serializable{ private int id; private String name; //無參數建構子 public Employee(){} //以下實作setter/getter public void setId(int id){this.id=id;} public int getId(){return id;} public void setName(String ...

Python AI-手寫辨識

Python AI-手寫辨識 類神經網路-手寫辨識 手寫辨識 (1) 問題定義 將輸入手寫數字圖片,經由類神經網路訓練後,可以辨識手寫圖片得到一個正確的答案,例如讓電腦辨識上面圖片手寫數字0-9,都可以認得.在了解問題後,需要先知道輸入的資料格式,例如圖片為NxN的矩陣向量. 輸入:輸入的資料格式有很多種,例如數字圖片為矩陣向量 模型:NN 輸出:輸出的方式,神經網路輸出不一定跟輸入同值,手寫數字輸入為1,輸出有可能是1.1或是1.5等等,所以輸出必須經過轉換成真實世界的數字. (2)定義函式 輸出會有兩個問題: A.輸出利用one-hot encoding來表示,就是N個狀態會對應N的結果,例如:輸出結果為1,表示[0,1,0,0,0,0,0,0,0,0] B.輸出結果不能超過1,我們通常會利用 Softmax函数 來進行輸出的處理. (3) 準備訓練/測試資料 在這邊需要從輸入去定義那些要當作訓練與測試資料,我們手寫資料使用MNIST 資料庫來訓練使用,MNIST共有70,000筆手寫資料,60,000筆為訓練資料,10,000為測試資料. (4)建構類神經網路模型 開始建構我們的神經網路模型,首先決定好28x28的像素(這邊不用擔心如何將圖片轉成矩陣),模型使用SGD的方式進行學習,輸出是一個10為的陣列來表示. 輸入:手寫數字圖片(28x28=784) 模型:SGD 輸出:數字(one hard encoding) (5)學習 首先介紹SGD(Stochastic Gradient Descent) 的學習方式,因為蕾神經網路需要訓練很多次才會提高準確度,SGD最大的好處就是當每次重新學習的會將訓練資料打散,來防止機器學習將答案死背下來. (6)實作開發 下面程式碼有完整的說明,這邊就不多說明了,當開始執行程式時就會進行資料訓練. 由訓練結果最後acc=0.9447,表示準確率可以到達94%,我們再由實際測試可以看出該圖為7的圖示,由神經網路判斷為7,跟我們人類判斷相同,我們可以知道由訓練的結果可看得到不錯的準確度. 執行神經網路遇到不少問題,請參考下面連結,是筆者所整理的問題集,請多多指教 https://programdoubledragon.bl...

Python AI-問題集

Python AI-問題集 問題集 Jupyter Notebook執行ipywidgets會出現kernel死掉的錯誤發生(The kernel appears to have died) 解決方法 (1) 根據log檔來判斷問題: 例如:log訊息出現OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized. (2) 根據問題關鍵字找出問題所在: 利用google查詢所遭遇到的問題,例如我把上面的問題上google查詢可以找到這篇的解法 https://blog.csdn.net/bingjianIT/article/details/86182096 (3)實作解法: 我實作下面解法後,就可以順利執行手寫辨識的程式. //在Python宣告時加入 import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" 參考 https://blog.csdn.net/bingjianIT/article/details/86182096