有没有办法从父级获取子级并检查(和使用)方法和属性?

时间:2019-07-04 10:59:37

标签: c#

我正在写一个将使用类并创建少量信息报告的类。问题是,即使它们都继承自基类,这些子类也不必实现所有相同的方法和属性。只是相关的...

我无法转换类,因为在设计时我不使用哪个类...我们有一个框架,并且开发人员在逐个工作的基础上采用它并实现一些特定于工作的代码。他们的基类有一些必须实现的方法(Init,Report,Audit),但是根据工作的类型,它将具有一些属性中的一个或两个以及一个或两个方法。  因此(如下面我的简单示例所示),他们可以实现Cat,但还需要与Cat类似的第二类,但又有足够的区别以保证可以创建新类,因此创建Cat2。 我知道这听起来很奇怪,但是当开发人员使用框架时,他们正在使用实例化的类。

class Animal
{
////common stuff
  public 
}

class Cat : Animal
{
  public Name { get; set; }
  public Speak() 
  {
    Console.WriteLine("Meow");
  }
}
class Dog: Animal
{
  public Name { get; set; }
  public Speak() 
  {
    Console.WriteLine("Woof");
  }
}
class Person: Animal
{
  public Title{ get; set; }
  public Name { get; set; }
  public Speak() 
  {
    Console.WriteLine("Hello");
  }
}
class Spider: Animal
{
  public Name { get; set; }

}


List<Animal> animals = new List<Animals> {
  new Cat { Name = "Bob" },
  new Dog { Name = "Fido" },
  new Person { Name = "Harry", Title = "Mr" },
  new Spider { Name = "Boris" }
}

foreach (Animal item in animals)
{
  ///now is wishful pseudo code...
  if item has Speak then speak()
  if item has Title then write Title
  if item has Name then write Name
}

我只想遍历列表,如果列表具有某种属性,请阅读该列表。如果它具有某种方法,请调用它。

2 个答案:

答案 0 :(得分:3)

  

如果它具有某些属性,请阅读它。如果它具有某种方法,请调用它。

听起来每个功能都定义了interface,即

interface IHazName { string Name {get;} }
interface IHazTitle { string Title {get;} }
interface ICanSpeak { void Speak(); }
...
foreach (Animal item in animals)
{
  if (item is ICanSpeak cs) cs.Speak();
  if (item is IHazTitle ht) Write(ht.Title);
  if (item is IHazName hn) Write(hn.Name);
}
...
class Cat : Animal, IHazName, ICanSpeak
{...}
class Dog : Animal, IHazName, ICanSpeak
{...}
class Person : Animal, IHazName, IHazTitle, ICanSpeak
{...}
class Spider : Animal, IHazName
{...}

关于使用接口的一个特别有趣的事情是,您可以对名称稍加捏造:

class Dog : Animal, IHazName, ICanSpeak
{
    //...
    public void Bark() { Say("woof"); } // method is called Bark on the public API
    void ICanSpeak.Speak() => Bark(); // but Speak on the ICanSpeak API
}

注意:此处的用法:

  if (item is ICanSpeak cs) cs.Speak();

需要现代的C#编译器;如果您使用的是较旧的编译器,则:

  if (item is ICanSpeak) ((ICanSpeak)item).Speak();

或:

  var cs = item as ICanSpeak;
  if (cs != null) cs.Speak();

同样,

void ICanSpeak.Speak() => Bark();

与较旧的编译器相同,

void ICanSpeak.Speak() { Bark(); }

答案 1 :(得分:0)

您可以添加一个新的抽象方法,然后在子类中实现它。

class Animal
{
    abstract Work();
}

class Cat : Animal
{
    public Name;
    public Speak();
    override Work()
    {
        Speak();
        Write Name;
    }
}
class Person: Animal
{
    public Title;
    public Name;
    public Speak();
    override Work()
    {
        Speak();
        Write Title;
        Write Name;
    }
}

foreach (Animal item in animals)
{
    item.Work();
}