哎呀概念查询

时间:2010-09-16 04:11:06

标签: c# .net oop polymorphism

我有一个与OOPS概念有关的问题。

我有一个基类

public class BaseClass
{
   public int i = 10;
   public int x = 30;
   public string str = "Hello";
   public virtual string Hello()
   {
     return "Hello of base class called";
   }
}

我有一个儿童班

public class ChildClass : BaseClass
{
    public int i = 20;
    public int z = 90;
    public override string Hello()
    {
       return "Hello of child class called";
     }
}

现在我已经看到下面的代码工作正常

BaseClass baseObject = new ChildClass();

当我输入 baseObject。时,我只会看到BaseClass的成员。

第一个问题:有人可以告诉我开发人员需要执行此操作的情况BaseClass baseObject = new ChildClass();吗?

第二个问题:如果我的BaseClass对象具有对我的子类对象的引用,那么为什么我的子成员变量无法通过此baseObject访问?

6 个答案:

答案 0 :(得分:7)

回答您的第一个问题。

开发人员这样做是为了提供他们所指的实际对象的抽象,这为使用它的代码提供了灵活性和“松散耦合”。

例如(常见场景 - 我经常使用),您可能有10个扩展基类的子类。如果您想要一种方法来返回每种类型的子类,该怎么办?好吧,如果没有这种类型的声明,你需要10种方法。但是如果指定了返回类型“BaseClass”,则可以从一个方法返回所有10种类型的子类。这种技术与接口用户密切相关。

E.g

public BaseClass GetDynamicChildClass()
{
     if (someCondition) return ChildClass();
     else if (someOtherCondition) return SomeOtherChildClass();
}

回答您的第二个问题。

您无法看到子属性,因为您说“baseObject”的类型为“BaseClass” - 编译器已将对象键入此属性。要访问子属性,您需要将其强制转换为子类型:

BaseClass b = new ChildClass();
int x = b.z; // error.
int x = ((ChildClass)b).z; // works - this is a cast, throws exception in bad conversion
ChildClass c = b as ChildClass; // also works, different type of cast, returns null in bad conversion
int x2 = c.z; 

这种类型的概念(多态)是面向对象编程的基础。看看这个出色的StackOverflow问题:Try to describe polymorphism as easy as you can

它以最简单的方式解释它,而不是将它绑定到任何特定的编程框架,在我看来,这是学习OO的最佳方式。

希望有所帮助。

答案 1 :(得分:1)

  1. 当您想拥有具有一组常用功能的具有个别行为的对象时。例如,您希望将不同类型的对象放入列表中。

  2. 底层类型仍然是ChildClass,但您目前正在使用BaseClass类型。这就是为什么你只看到BaseClass的成员。尽管如此,仍然可以使用强制转换操作或'as'关键字将BaseClass实例转换为ChildClass实例。

答案 2 :(得分:1)

当你这样做时

BaseClass baseObject= new ChildClass();

对象的静态声明类型是“BaseClass”。

因此,您只能看到"BaseClass"类型的对象。

如果您确定该对象是ChildClass Type,则可以将baseObject类型转换为“ChildClass”,然后使用ChildClass成员

((ChildClass) baseObject). - 应该帮助intellisense为您提供子类的成员。

使用BaseClass baseObject= new ChildClass(); RunTime多态 的基础。 如果您需要调用重写的子逻辑但接口是基类的接口,则它非常常用

编辑:您将使用它的场景示例 类User派生了名为Employee3rdPartyUser

的类

Class User有一个名为GetRoleInformation的虚方法 - 用于从公司Active目录中获取用户的角色信息。

但是,对于第三方用户,由于AD中不存在该信息,因此获取角色信息的逻辑涉及调用Web服务来检索数据。 在这种情况下,GetRoleInformation在3rdPartyUser类中重写

现在,在程序中,在登录页面上,一旦通过身份验证,我就会找回Employee或3rdPartyUser的对象。 我将此对象传递给具有签名RoleCollection GetRole( User loggedInUser)

的方法

在此方法中,无需确定用户的类型,我只需调用loggedInUser.GetRoleInformation,并根据它是否为Employee / 3rdPartyUser,将调用相应的基本/重写方法,并且角色数据将从AD / Web服务中检索。

长话短说:

的优点
BaseClass baseObject= new ChildClass();

OVER

ChildClass baseObject= new ChildClass();
当您不确定将要分配给baseObject变量的子对象的确切类型时,

就是在这种情况下:例如:Employee / 3rdPartyUser 例如:

  BaseClass baseObject= GetLoggedInUser();

此方法的签名为User GetLoggedInUser(string userid)

否则,在像你这样的例子中,对象总是类型为“ChildClass”,我相信这样做是没有好处的。

答案 3 :(得分:1)

这是一个示例,其中我们关心的唯一方法是在基类中。通过使用这种抽象,我们可以轻松添加更多报告类型。

public class Report
{
    public virtual string ContentType
    {
        get { return "application/octet-stream"; }
    }

    public virtual byte[] Build()
    {
        return new byte[0];
    }

    public static Report Create(ReportType type)
    {
        switch (type)
        {
            case ReportType.Pdf:
                return new PdfReport();
            case ReportType.Html:
                return new HtmlReport();
            case ReportType.Doc:
                return new DocReport();
            case ReportType.Xls:
                return new XlsReport();
            default:
                return new DefaultReport();
        }
    }
}

然后从客户端我们只需要这样做:

ReportType type = GetReportTypeFromFormPost();
Report report = Report.Create(type);
// ...
Response.Write(report.Build());

答案 4 :(得分:1)

你的第一个问题的答案: 这种类型的实现很常见,当我们使用抽象工厂模式时,我会给你一个简单的例子来创建一个家庭福特汽车..

public class AbstractFactoryExample
{
    public AbstractFactoryExample()
    {
        string type = "";
        CarFactory facotry=null;
        if (type == "FORD")
        {
            facotry = new FordCarFactory();
        }
        ICar MyFamilyCar = facotry.CreateFamilyCar();
        ICar MyCityCar = facotry.CreateCityCar();
    }
}
public interface ICar
{

}
public abstract class CarFactory
{
    public  abstract ICar CreateFamilyCar();
    public  abstract ICar CreateCityCar();

}
public class FordCarFactory : CarFactory
{
    public  override ICar  CreateFamilyCar()
    {
        return new FordFamilyCar();
    }
    public override ICar CreateCityCar()
    {
        return new FordCityCar();
    }
}
public class FordFamilyCar : ICar
{

}
public class FordCityCar : ICar
{

}

到你的第二个问题:

您将对象声明为基类,因此它仅显示其中的方法,如果您确定生成的实例是子类的类型

((ChildClass) baseObject) 

可以解决问题

请原谅我的英语不好

答案 5 :(得分:0)

实际上,当您使用Factory Pattern(http://gsraj.tripod.com/design/creational/factory/factory.html)实例化对象时,对您来说更有意义。这会将实现特定的细节抽象到不同的类。