2016-05-31 43 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() 
相关问题