2016-05-31 49 views
0
public class BaseClass 
    { 
     public virtual void Display() 
     { 
      Console.WriteLine("I am Base Class"); 
     } 

     public void BaseClassMethod() 
     { 
      Console.WriteLine("I am Base Class Method"); 
     } 
    } 

    public class DerivedClass : BaseClass 
    { 
     public override void Display() 
     { 
      Console.WriteLine("I am Derived Class"); 
     } 

     public void DerivedClassMethod() 
     { 
      Console.WriteLine("I am Derived Class Method"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      BaseClass bc = new BaseClass(); 
      bc.Display(); 
      bc.BaseClassMethod(); 

      Console.WriteLine("--------------"); 

      DerivedClass dc = new DerivedClass(); 
      dc.Display(); 
      dc.BaseClassMethod(); 
      dc.DerivedClassMethod(); 

      Console.WriteLine("--------------"); 

      BaseClass bc2 = new DerivedClass(); 
      bc2.Display(); 
      bc2.BaseClassMethod(); 
      //bc2.DerivedClass(); --> I can't reach b2.DerivedClass() method 

      Console.ReadLine(); 
     } 
    } 

大家好。我試圖清除我爲什麼和我想在哪裏創建和使用基類引用的派生類對象。我知道如何虛擬作品。我知道派生類是一個基類,我可以覆蓋虛擬方法。我可以在基類中訪問非虛擬方法。但我想知道哪裏可以,爲什麼我想要使用這種風格的對象創建。就像我在示例代碼的最後部分一樣;爲什麼我要創建一個具有基類引用的對象?

BaseClass bc2 = new DerivedClass(); 

我無法到達派生類方法,所以我不能使用派生類方法。但由於新的DerivedClass,它仍然是派生類。如果我使用正常的DerivedClass d = new DerivedClass();樣式,我可以使用這兩種類的方法。我只是找不到任何理由和情況,我想用這種風格。我會很高興,如果有人告訴我在哪種情況下我必須使用基類引用的派生類對象,所以我可以理解這種風格存在於語言中。我想知道爲什麼,我不是問爲什麼這不起作用或類似的東西。只想知道情況。謝謝。

+0

你有沒有對'Class Inheritance'進行任何閱讀/研究?也許你可以考慮在'OOP'上做一個'C#MSDN Google Search'並且瞭解誰在哪裏以及爲什麼 – MethodMan

+0

好,當你只有一個基類時,以及一個派生類,你不會去找到很多價值。這是當你有多個具有通用功能的類時,而且還有不同的實現路徑,你將從繼承中受益。 – Jonesopolis

+0

簡介:它向讀者表明,該對象不會被用於比基類功能集所提供的任何更多的功能。聲明派生類型將是「邏輯噪聲」。這不是讓事情變得比需要更復雜。使用適合這項工作的工具。 –

回答

2

主要有兩種用途:多種類型的

讓我們改變你的例子有點

public class Shape 
{ 
    public virtual void Display() 
    { 
     Console.WriteLine("I am a Shape"); 
    } 

    public void BaseClassMethod() 
    { 
     Console.WriteLine("I am Base Class Method"); 
    } 
} 

public class Square : Shape 
{ 
    public override void Display() 
    { 
     Console.WriteLine("I am Square"); 
    } 

    public void DerivedClassMethod() 
    { 
     Console.WriteLine("I am Derived Class Method"); 
    } 
} 



public class Circle : Shape 
{ 
    public override void Display() 
    { 
     Console.WriteLine("I am Circle"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Shape> shapes = new List<Shape(); 
     shapes.Add(new Square()); 
     shapes.Add(new Circle()); 

我有一個可容納圓形,方形和一個列表

1)集合通用形狀都集中在一個集合中。

2)多態性

從前面的代碼

  foreach(Shape shape in shapes) 
     { 
      shape.Display(); 
     } 

我們不知道的是,但我們知道什麼樣的Shape變量shape,這是任何種類將有繼續上我們可以調用一個Display()方法,它會顯示正確的信息。

當你需要調用某個函數時,多態性很有用,但你不知道具體的類型,因爲你正在拉取上面的基類型集合,或者你想編寫一個函數因爲函數不需要知道具體的類型來完成它的工作,所以可以採取任何類型的Shape

public static void LogDisplay(Shape shape) 
    { 
     Console.WriteLine("I am about to call shape.Display()"); 
     shape.Display(); 
     Console.WriteLine("I am just called shape.Display()"); 
    } 
+0

謝謝你的回答。還有其他有益的答案,但我接受你的答案,因爲它是第一個答案。這是否意味着當我創建一個正方形或圓形shapes.Add(new Square()); ,是在List中使用基類引用創建的這個對象。 – alpersilistre

+1

我不完全相信我理解你的問題,但我認爲答案是「是」。 –

2

我最喜歡的例子,因爲人們可以理解使用,正在記錄。想象一下,我創建了一個網站。當我開發網站時,我想登錄到我的文件系統,因爲它很容易訪問。當我部署網站時,我想登錄到事件日誌,因爲可能我沒有直接訪問該計算機上的文件系統。

但是,我只想改變事物的記錄位置,我希望基類構造實際文本的外觀。所以我有一個格式化的文字我的基類:

public abstract class BaseLogger 
{ 
    public abstract void LogException(Exception ex); 
    public abstract void LogUserMessage(string userMessage); 

    protected string GetStringFromException(Exception ex) 
    { 
     //.... 
    } 

    protected string GetStringFromUserMessage(string userMessage) 
    { 
     //.... 
    } 
} 

現在我可以有一個記錄到文件系統的一類:

public class FileLogger : BaseLogger 
{ 
    public FileLogger(string filename) 
    { 
     //initialize the file, etc 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromException(ex); 
     File.WriteAllLines(...); 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromUserMessage(ex); 
     File.WriteAllLines(...); 
    } 
} 

和我的類記錄到事件日誌:

public class EventLogger : BaseLogger 
{ 
    public EventLogger() 
    { 
     //initialize the eventlog, etc 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromException(ex); 
     EventLog.WriteEntry(...); 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromUserMessage(ex); 
     EventLog.WriteEntry(...); 
    } 
} 

現在在我的程序中,我只在乎我有一個BaseLogger,當我在我的課程中注入一個。實現細節無關緊要,我只知道無論我使用什麼,我都可以使用LogExceptionLogUserMessage

當我是使用記錄器我受益於不關心哪個派生類我使用。這是將每個派生類視爲基類的好處。如果沒有我的程序關懷,我可以將它們交換出去。

0

我相信很多使用派生類的可用性背後的推理與最小化重複代碼有關。

引用一個現實生活中的例子... 如果我要讓你描述汽車的屬性和能力,然後要求你對電動汽車做同樣的事情,那麼你會發現那麼多屬性和能力由兩者共享。因此,創建基類Car並從中派生ElectricCar會更有效,而不是兩個完全分離的類。那麼你只需要考慮派生類中電動車的具體差異,所有的共享屬性和能力就會隨之而來。

希望這有助於你理解基類和派生類的用處。非常簡單,但我覺得它可以幫助你理解這個概念!

1

要做到這一點有很多原因,主要是與代碼重用性和可擴展性有關,換句話說,即使不需要重新編寫大量代碼,也可輕鬆進行小改動或增強。

一個現實世界的例子(經常發生)就是你有不同的客戶使用你的軟件,可能需要你支持不同的數據庫(甚至不同的表結構)。因此,爲了做到這一點,您可以從一個公共基類中派生實現,並且在實現細節上有所不同,而不會影響程序的其餘部分。

這也遵循的設計原則「計劃 一個‘口’,而不是‘執行’」,這是在

public abstract class ProviderBase 
{ 
    public abstract Employee[] GetAllEmployees(); 
} 

public class MySqlProvider:ProviderBase 
{ 
    public override Employee[] GetAllEmployees() 
    { 
     string select = "select * from employees"; 

     //query from mysql ... 
    } 

} 

public class MsSqlProvider : ProviderBase 
{ 
    public override Employee[] GetAllEmployees() 
    { 
     string select = "select * from user u left join employee_record e on u.id=e.id"; 

     //query from mysql ... 
    } 
} 

解釋然後在主程序中,你可能會能夠通過配置更改數據庫實施的類型或Dependency Injection

ProviderBase provider = null; 
if(databaseType == "MySql") 
{ 
    provider = new MySqlProvider(); 
} 
else if (databaseType == "MsSql") 
{ 
    provider = new MsSqlProvider(); 
} 

var employees = provider.GetAllEmployees(); 
//do something 
0

主要原因使用基類是重用多態性

所以,你可以創建根據條件的類:

BaseClass bc 
if(case1) 
    bc = new DerivedClass1(); 
else 
    bc = new DerivedClass2(); 

在下面的應用程序,您可以使用bc即使你不知道什麼樣的派生類在編譯時。你可以通過例如其它的功能,並調用重寫梅索德:當你知道什麼樣的派生類的你實際有

bc.Display(); 

派生類方法只能使用。然後你可以做一個轉換。

DerivedClass1 dc = bc as DerivedClass1; 
dc.DerivedClassMethod() 
相關問題