我有一个与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
访问?
答案 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)
当您想拥有具有一组常用功能的具有个别行为的对象时。例如,您希望将不同类型的对象放入列表中。
底层类型仍然是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
派生了名为Employee
和3rdPartyUser
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)实例化对象时,对您来说更有意义。这会将实现特定的细节抽象到不同的类。