继承和传递参数

时间:2014-11-06 19:59:48

标签: c# oop

假设我有班级家长

       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
     }

7 个答案:

答案 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以及所有继承的类型。因此,您可以使用ParentChild对象调用您的方法。

但在我看来,你应该重新考虑使用继承。在我看来,过度使用的模式通常会导致错误的代码。例如,每个人总是Child但不是每个人都是Parent。但每个人都可以成为Parent,但他自动成为Parent a Child。因此,您在代码中的思考方式与现实并不相似。

实际上代码不一定与现实相似,但你应尽量保持灵活性。如果不是,您很可能在以后遇到实现新功能的问题。而且,根据我的经验,这种情况迟早会发生。

相反,你应该在Behaviours中考虑更多。 Parent应该做什么,哪个功能有Child?您应该考虑这一点,而是编写一个类似于此行为的接口。

例如,当两者都有名字时,你应该写。

interface INameable {
    string Name { get; }
}

你接下来要做的是创建你的类。

class Parent : INameable { ... }
class Child : INameable { ... }

不同之处在于您创建了多个类似于不同行为的界面。例如,如果您想编写一个只需要具有Name属性的对象的方法,那么就可以编写。

Method(INameable obj)

为什么这样更好?您还可以编写可能永远不会从ParentChild继承但仍具有名称且对该方法有效的类。例如。

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特定属性,则需要进行投射,并且没有人可以保证它实际上是ChildParent个实例。可以传递任何在其继承层次结构中具有Parent的类。

答案 6 :(得分:0)

您可以使用Parent的类型创建方法,它将同时适用于

void DoSomething(Parent parent)
{
}