iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
自我挑戰組

初階面試常見題目彙整系列 第 3

初階面試常見題目回答-繼承-鐵人賽第三日

  • 分享至 

  • xImage
  •  

至盤古開天闢地以來
我想各位對繼承的含意,
各有各樣的見解,
我想對最初各位都有所見解。

https://ithelp.ithome.com.tw/upload/images/20230913/20162039E2iEG8n0Ii.png

雖然我知道各位對於繼承在於蝌蚪的時候都有感受了,
但還是不免俗的來一下介紹。

繼承(Inheritance)

繼承可讓您建立新類別以重複使用、擴充和修改其他類別中所定義的行為。

其中可以看到三個關鍵字,
根據這三個字我們可以再找到更多內容。

1.擴展(Extend):
擴展指的是在派生類別(子類別)中添加新的屬性和方法,以滿足特定需求,同時保留了從基底類別(父類別)繼承來的特性。這允許你將基底類別的功能進行擴展,使得派生類別具有更多的功能。

2.重寫(Override):
重寫是指在派生類別中重新定義基底類別的方法。這允許你修改方法的行為,使其適應派生類別的特定需求。重寫方法的名稱、參數和返回類型必須與基底類別中的方法一致,但方法的實際實作可以完全不同。

3.重用(Reuse):
重用是指在派生類別中直接使用基底類別繼承來的屬性和方法,而不進行修改或擴展。這允許你在派生類別中重用基底類別的通用功能,同時避免重複編寫相同的程式碼。

那麼定義的部分說完了,我這邊快速地用自己理解的描述擴展、重寫和重用

Extend:
就是所謂的繼承後的class要在新增屬性或方法。
Override
就是重新定義同樣的東西,把資料覆寫過去,又叫做覆寫,這兩個都同樣地。
Reuse
可以用該class底下的function,避免重寫

那麼主要目的,是為了避免重寫相同的程式,與功能的擴展,也可以輕易創建出類似的許多子類別,提供多種用法。
當然這個功能,也是最容易別人弄不好而導致出現些問題的功能,
不過這邊筆者先帶大家聚焦於,
在什麼情況下繼承會被限制一定的功能,
有三種狀況會需要特別提一下。

分別是
final、建構子(constructor)、private

其中final筆者不就多著墨,
從字面上就說是最終了,
自然而然是無法被繼承的。

constructor
在程式裡面,建構子是無法被繼承,但是是可以使用值的。

舉個例子,在父類別的建構子的屬性塞入"Hi",
在子類別直接讀該屬性會是預設值。
但是呢,是可以用值的,
例如在C#中可以透過base進行調用,(C#在父類別沒參數的狀況下,會自動用base)
這時候讀到的值就會是父類別建構子裡面的值了。

把這個例子轉換成程式碼的話,並進行一點潤色的話

首先創建Class

    class ParentClass
    {
        public string shadowMessage;
        public string overridMeessage;
        public string message;

        public ParentClass()
        {
            shadowMessage = "Hi";
            overridMeessage = "XXX";
        }

        public virtual string OverridMeessage
        {
            get { return overridMeessage; }
            set { overridMeessage = value; }
        }
        public virtual string Message
        {
            get { return message; }
            set { message = value; }
        }
    }

    class ChildOverwriteClass : ParentClass
    {
        public new string shadowMessage;

        public ChildOverwriteClass() : base()
        {
            message = "OOO";
        }

        public override string OverridMeessage
        {
            get { return "Hello from ChildClass"; } // 在子類別中重寫 Message 屬性的 getter
        }
    }

實際案例說明

        ParentClass parentClass = new ParentClass();
        ChildOverwriteClass childOverwriteClass = new ChildOverwriteClass();

        //"Hi"  public 可  protected 不可  private 不可
        string parentClassshadowMessage = parentClass.shadowMessage;
        
        //"XXX"  public 可  protected 不可  private 不可
        string parentClassoverridMeessage = parentClass.overridMeessage;
        
        //null  public 可  protected 不可  private 不可
        string parentClassmessage = parentClass.message;
        
        //"XXX"  public 可  protected 可  private 可
        string parentClassOverridMeessage = parentClass.OverridMeessage;
        
        //null  public 可  protected 可  private 可
        string parentClassMessage = parentClass.Message;
        
        
        
        //  public 可  protected 可  private 可
        //shadowMessage遮蓋(shadow)父類別中的 message屬性 : null
        string childOverwriteClassshadowMessage = childOverwriteClass.shadowMessage;
        
        //  public 可  protected 不可  private 不可
        //overridMeessage 調用到父類別 : "XXX"
        string childOverwriteClassoverridMeessage = childOverwriteClass.overridMeessage;
        
        //  public 可  protected 不可  private 不可
        //message 調用到父類別 由於子類別有建構子 : "OOO"
        string childOverwriteClassmessage = childOverwriteClass.message;
        
        //  public 可  protected 可  private 可
        //Hello from ChildClass  >> 調用到Overwrite : "Hello from ChildClass"
        string childOverwriteClassOverridMeessage = childOverwriteClass.OverridMeessage;
        
        //  public 可  protected 可  private 可但因message在建構子不可,所以不可,所以應該要給可
        //Message 調用到父類別 由於子類別有建構子 : "OOO"
        string childOverwriteClassMessage = childOverwriteClass.Message;

註解中的
// public 可 protected 不可 private 不可
是基於基底屬性設定為protected,
各位可以看到會是沒有辦法直接呼叫該屬性的,
但關於此詳細的內容,用這簡短的範例有點難展示出來,
所以各位對這內容有興趣的話,
還請多加嘗試,

那麼以上兩個,
一個是完全不能繼承,
另一個是繼承很麻煩,
我只想要限制某個屬性,
不想搞那麼複雜要怎麼辦。
這時候就輪到封裝的Private上場啦!

改成Private就可以限制讓子類別不去使用,
不過說到這裡,
可能會有些人想到,
不是很常遇到私人屬性,
為了取值寫了個公開的取值器。

那麼就有一個奇怪的問題,
如果private不能繼承
我寫了一個取值器的function
那麼繼承了之後會是怎麼樣的?

答案會是可以繼承,但是不能使用,
因為裡面必要屬性會是私人的,
導致不能使用。

如果你是使用Visualstudio編譯的話,
會出現父類別.私人屬性由於其保護層級之故 所以無法存取

那麼一連串的說下來,
可以發現繼承的依賴性超強,
這是優點也是缺點,
在往後的很多規則,
其實就會看到又是繼承,
但又不得不說這是必須的。

----梗出處
"人和妖精都是媽生的" 《大話西遊2:仙履奇緣》唐僧 - 唐三藏

---參考

https://wucodingroad.blogspot.com/2016/02/java-Constructor.html
前輩所寫的建構子各種嘗試方式與更詳細的使用條件與方法

https://learn.microsoft.com/zh-tw/dotnet/csharp/fundamentals/object-oriented/inheritance
microsoft 繼承 - 衍生類型以建立更特製化的行為

---筆者後言
最初的草稿是打算用富豪汽車的三點式安全帶繼承來寫,
但寫完後故事的存在感太強,
所以臨時改寫,
有點難過。

其次,
由於沒辦法得很好展現protected的效果,
決定廢棄只用Private跟Public來進行展示,


上一篇
初階面試常見題目回答-封裝-鐵人賽第二日
下一篇
初階面試常見題目回答-多型-鐵人賽第四日
系列文
初階面試常見題目彙整30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言