iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
自我挑戰組

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

初階面試常見題目回答-多型-鐵人賽第四日

  • 分享至 

  • xImage
  •  

多型(Polymorphism)
多型是指同一個方法名稱可以被不同的類別實作以產生不同的行為。
通常來說有兩種最具代表性的作法
Overload(多載)、Override(覆寫)

Overload有很多種形式,
像筆者想到的有「函式多載」(Function Overloading)和「方法重載」(Method Overloading),
一個是在函式,而另一個常在類別,
不過筆者這邊就不區分這部分的細節,
都把它統整在Overload中。

那麼Overload的作法是什麼呢?

簡單來說,
會是一種傳入參數不同的function,
也就是所謂的多型(Polymorphism)。

舉個實際的例子,
我們要移動會動用到Move,
可透過不同載具移動的話,
會用到不同傳入參數。

例如汽車需要Gasoline(汽油)、腳踏車需要humanity(人類)與cal(卡路里)而人類需要cal(卡路里),
可以看到要達成Move所需要的傳入參數各不相同,
這就是所謂的Overload。

轉換為程式碼會是這樣子。

namespace Car.Model
{
    public class MoveModel
    {
        //載具,假定汽車
        public void Move(int Gasoline)
        {
            #region 流程

            if (Gasoline >= 1)
            {
                Console.WriteLine("Car is moving.");
                Gasoline--;
            }
            else
            {
                Console.WriteLine("Car is out of fuel.");
            }
            #endregion 流程
        }

        //人力載具,假定腳踏車
        public void Move(int humanity, double cal)
        {
            #region 流程

            if (humanity >= 1 && cal >= 1)
            {
                Console.WriteLine("Bicycle is moving.");
                humanity--;
                cal -= 1;
            }
            else
            {
                Console.WriteLine("Bicycle cannot move.");
            }
            #endregion 流程
        }

        //單純以人力移動,假定走路
        public void Move(double cal)
        {
            #region 流程
            if (cal >= 1)
            {
                Console.WriteLine("Human is moving.");
                cal -= 1;
            }
            else
            {
                Console.WriteLine("Human does not have enough energy to move.");
            }
            #endregion 流程
        }
    }
}

在這邊會發現一個點,
在Overload中所關注會是傳入參數,
那麼傳出參數呢?

通常來說不會透過傳出參數進行判斷,
這基於編譯器會很困難判斷,
而且會是很難使用的,
如果傳出參數不一要接續去使用會是很困難的。

就以剛剛的例子,
消耗了一定數量的Gasoline(汽油)移動了一段距離,
我們就能明確知道是某個使用汽油的交通工具,
像這裡就能是假設是汽車。

但是移動傳出是以公里、公尺、英尺,
很容易混淆說,
到底是以人還是車或腳踏車,
基於功能相似與返回值難以區分,
所以沒有透過傳出參數多型,
至少筆者至今沒看過。

那這種以寬度來製作的多型,
在逐漸製作的過程中會逐漸遇到缺點,
這一部分我暫且不談,
先談回Override(覆寫)。

那麼Override呢?
為什麼Override會是多型?
可能有些人會認為,不就是相同的傳入傳出,
並改寫內容,為什麼會是多型,
不僅僅是方法的內容被覆寫,
更重要的是方法的行為在不同的物件實例下具有不同的實現。

從昨天例子可以看到,
原本在父類別的時候是"Hi",
可以看到被Override的時候,
就出現不同的實現。

那麼,在大概解說完畢後!
我想回歸到標題,
初階面試,
在OOP(物件導向概念)的基礎大致要解說完成時,
是時候舉個我遇到過的比較特殊的問題。

在所有題目,其他題目都是,
我知道他們是什麼,但你要我說出個所以然,
在沒準備的狀況會是非常模糊,以至於說不出來,
除了這一題,我一臉茫然,一副不知道到底在說甚麼。

提問者:封裝、繼承、多型有聽過嗎?
筆者:是的,有學過,對它有一定的印象

提問者:new 一個class是這三個(封裝、繼承、多型)之中的哪一個

筆者非常害羞懷疑的說:
應該是封裝,可是又可能有繼承,
不可能是多型。

提問者回答:就是多型

筆者:???恩,是這樣...麻?...

.......帶過

這個題目還蠻有趣,
以至於我後續花了點時間研究面試者的想法,
那這邊我先來說說筆者的想法。

new 一個class是這三個之中的哪一個
以此問題來說,
這個描述是實例化(Instantiation)最常見的聽到的解釋,
他的作用就是定義,
創建出一個可用的物件,
分配記憶體給他,
然後以利後續的操作。
Instantiation對筆者來說來說最深的印象是定義與創建,
但很可惜的是,
面試官帶來的問題不是Instantiation,
而是一個最常見的回答,
那麼帶回來我的回答與問題。

new 一個class是這三個之中的哪一個

new一個class是封裝,也有可能是繼承。
不可能是多型。

這句話的意思是
封裝是一定有的,因為new一個class只會給別人看到class而內部細節不會給人看到,所以屬於封裝。
也有可能是繼承,因為不知道該class有沒有父類別,有的話即是繼承
不可能是多型,因為new一個class的動作實際上根本沒出現所謂的相同的方法function名稱。

但,
很可惜的是,
筆者的描述沒有傳達給面試官,
而是停留在筆者害羞內向的回答,
而話至於此,
跟人心意相同可是難度非常高的。
筆者當下沒去解釋也沒反駁,
在後續查閱一陣子資料,
篤定了筆者自身有很大的可能性沒有錯誤後,
筆者思慮了一天多有去寄信,
之後會來針對面試官跟筆者對自身的檢討,
來作解尾,
不過由於沒有再去徵求面試官的意見,
筆者不會去貼出面試官的回答,
由於遮掩了部分的事實,
會是難以判斷對錯,
也有可能是筆者曲解,
這方面還請各位用作參考之用。

---各種可供參考的連結

Overload 多載觀念
https://notfalse.net/58/overload#i

JAVA-SE 6 技術手冊-多型(Polymorphism)
https://caterpillar.gitbooks.io/javase6tutorial/content/c8_2.html

黑暗執行續-方法多載(Method Overloading)與 dynamic
https://blog.darkthread.net/blog/overloading-and-dynamic/


上一篇
初階面試常見題目回答-繼承-鐵人賽第三日
下一篇
初階面試常見題目回答-OOP物件導向概念-鐵人賽第五日
系列文
初階面試常見題目彙整30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言