假设我有班级家长
public class Parent
{
//several properties... P1,P2..etc
}
另一个班级
public class Child:Parent
{
//several new properties C1,C2..etc
}
是否可以编写一个可以接受父类型或子类型的函数A?
private void DoSomething( Child/Parent A, bool IsParent)
{
//process additional child properties if IsParent is false
}
答案 0 :(得分:6)
由于继承,Parent
类型的参数总是接受Child
类型的对象。
更大的问题实际上是IsParent
。如果不检查您的不任何子类型,则无法确定。因为基础类型不应该知道它们的推导,所以无论如何你都不会这样做。
更有可能;您可以DoSomething
virtual
,这样您就可以在每个派生类中使用不同的实现。
答案 1 :(得分:3)
你可以超载它。
void DoSomething(Child child)
{
DoSomething((Parent) child);
//process child specific logic
}
void DoSomething(Parent parent)
{
//process parent
}
根据您的代码,您甚至可能不需要bool IsParent
。
如果您只有 base 实例,但如果它是Child
实例,则需要使用它,您可以检入代码并处理额外的逻辑。
void DoSomething(Parent parent)
{
var child = parent as Child;
if (child != null)
DoSomethingForChild(child);
}
void DoSomethingForChild(Child child)
{
}
答案 2 :(得分:2)
...不确定
private void DoSomething(Parent parent)
{
if (parent is Child)
{
var child = parent as Child;
// do something with child here
}
}
以下是一个简单用法的示例:
public class Parent { public string Name { get; set; } }
public class Child : Parent { public Parent Parent { get; set; } }
public static void Introduce(Parent p)
{
Console.WriteLine("Hello, my name is: {0}", p.Name);
if (p is Child)
{
Child c = p as Child;
Console.WriteLine(" - and my parent's name is: {0}", c.Parent.Name);
}
}
private static void GenericTester()
{
Parent p = new Parent {Name = "Dad"};
Child c = new Child {Name = "Son", Parent = p};
Introduce(p);
Introduce(c);
}
// Ouput:
// Hello, my name is: Dad
// Hello, my name is: Son
// - and my parent's name is: Dad
答案 3 :(得分:2)
使用继承时,名称已经表明您从其他类型继承。如果您创建的类Child
继承自类Parent
并且您具有以下方法
public Method(Parent obj)
这意味着它接受Parent
类和以及所有继承的类型。因此,您可以使用Parent
或Child
对象调用您的方法。
但在我看来,你应该重新考虑使用继承。在我看来,过度使用的模式通常会导致错误的代码。例如,每个人总是Child
但不是每个人都是Parent
。但每个人都可以成为Parent
,但他自动成为Parent
和 a Child
。因此,您在代码中的思考方式与现实并不相似。
实际上代码不一定与现实相似,但你应尽量保持灵活性。如果不是,您很可能在以后遇到实现新功能的问题。而且,根据我的经验,这种情况迟早会发生。
相反,你应该在Behaviours
中考虑更多。 Parent
应该做什么,哪个功能有Child
?您应该考虑这一点,而是编写一个类似于此行为的接口。
例如,当两者都有名字时,你应该写。
interface INameable {
string Name { get; }
}
你接下来要做的是创建你的类。
class Parent : INameable { ... }
class Child : INameable { ... }
不同之处在于您创建了多个类似于不同行为的界面。例如,如果您想编写一个只需要具有Name
属性的对象的方法,那么就可以编写。
Method(INameable obj)
为什么这样更好?您还可以编写可能永远不会从Parent
或Child
继承但仍具有名称且对该方法有效的类。例如。
class Car : INameable { ... }
class Dog : INameable { ... }
...
您还应该注意,一个类不仅可以有多个接口。
为了减少多重实施,您还应该使用合成而不是继承。因此,不应通过继承实现代码重用,而应使用其他对象来创建更大的类。这些通常会导致更小的类,更分离,更容易维护。你还会看到你经常有更好的代码重用,并且不会以继承地狱结束我的称呼。
答案 4 :(得分:1)
我要问的第一个问题 - 这两个对象之间是否存在关联,以便通过使用基于面向对象的主体来减少复杂性?
如果是这样,您可以创建Child和Parent类必须实现的接口,例如
interface IParent
{
string Name {get; set;}
string Age {get; set;}
}
class Child
{
Parent Parent {get; set;}
}
class Parent
{
IEnumerable<Child> Children {get; set;}
}
...
class Parent : IPerson
class Child : IPerson
...然后让您的方法接受 IPerson ,例如
void DoSomething(IPerson person)
{
if(person is Child)
{
var child = person as Child;
}
else if (person is Parent)
{
var parent = person as Parent;
}
}
你要问的问题是,这在你的上下文中是否有意义?
在不了解细节的情况下,许多更简单的方法(如重载)与解决问题的方法一样好。
答案 5 :(得分:0)
是的,当您将参数指定为Child
时,您可以传递Parent
个以及Parent
个对象。
如果您想要访问Child
特定属性,则需要进行投射,并且没有人可以保证它实际上是Child
或Parent
个实例。可以传递任何在其继承层次结构中具有Parent
的类。
答案 6 :(得分:0)
您可以使用Parent的类型创建方法,它将同时适用于
void DoSomething(Parent parent)
{
}