C# 关注点分离与多态设计

C# 关注点分离与多态设计,c#,C#,比如说,我试图对动物的行为和外观进行建模,我想让每个动物的代码和动作/外观的代码分开。我如何用C#建模 这将是理想的: using System.Collections.Generic; class PaintingAnimals { class Animal {} class Cat : Animal {} class Dog : Animal {} static void Paint(Cat cat) { System.Console.WriteLine("Cat");

比如说,我试图对动物的行为和外观进行建模,我想让每个动物的代码和动作/外观的代码分开。我如何用C#建模

这将是理想的:

using System.Collections.Generic;

class PaintingAnimals {
  class Animal {}
  class Cat : Animal {}
  class Dog : Animal {}

  static void Paint(Cat cat) { System.Console.WriteLine("Cat"); }
  static void Paint(Dog dog) { System.Console.WriteLine("Dog"); }
  static void Paint(Animal animal) { System.Console.WriteLine("Animal"); }

  public static void Main() {
    var animals = new List<Animal> {new Cat(), new Dog()};

    foreach (var animal in animals) {
      Paint(animal); // Always prints "Animal" not "Cat" or "Dog"
    }
  }
}
使用System.Collections.Generic;
绘画类动物{
类动物{}
类别猫:动物{}
狗类:动物{}
静态无效绘制(Cat){System.Console.WriteLine(“Cat”);}
静态void Paint(Dog-Dog){System.Console.WriteLine(“Dog”);}
静态虚空绘制(动物){System.Console.WriteLine(“动物”);}
公共静态void Main(){
var animals=新列表{new Cat(),new Dog()};
foreach(动物中的动物变量){
绘画(动物);//总是打印“动物”而不是“猫”或“狗”
}
}
}

但是,如果我理解正确,只有当
Paint
定义为
Paint(动物)
,而不是
Paint(猫)
Paint(狗)时,此代码才会编译
因此,我不能将每种动物的代码拆分为不同的函数,这样狗和猫的颜色就会不同。

您要做的不是调用以动物为参数的方法,而是调用动物上的方法:

static void Main() {
  var animals = new List<Animal> {new Cat(), new Dog()};

  foreach (var animal in animals) {
    animal.Paint();
  }
}
static void Main(){
var animals=新列表{new Cat(),new Dog()};
foreach(动物中的动物变量){
动物漆();
}
}

每一个具体的动物类都将根据自己的意愿实现绘画方法。

在研究@AlexeiLevenkov的建议后,我发现以下代码可以实现我想要的:

using System.Collections.Generic;

class PaintingAnimals {
  class Animal {}
  class Cat : Animal {}
  class Dog : Animal {}

  static void Paint(Cat cat) { System.Console.WriteLine("Cat"); }
  static void Paint(Dog dog) { System.Console.WriteLine("Dog"); }
  static void Paint(Animal animal) { System.Console.WriteLine("Animal"); }

  public static void Main() {
    var animals = new List<Animal> {new Cat(), new Dog()};

    foreach (dynamic animal in animals) { // Uses "dynamic", not "var"
      Paint(animal); // Print's "Cat" and "Dog" respectively, not "Animal"
    }
  }
}
使用System.Collections.Generic;
绘画类动物{
类动物{}
类别猫:动物{}
狗类:动物{}
静态无效绘制(Cat){System.Console.WriteLine(“Cat”);}
静态void Paint(Dog-Dog){System.Console.WriteLine(“Dog”);}
静态虚空绘制(动物){System.Console.WriteLine(“动物”);}
公共静态void Main(){
var animals=新列表{new Cat(),new Dog()};
foreach(动物中的动态动物){//使用“动态”,而不是“var”
画(动物);//分别画“猫”和“狗”,而不是“动物”
}
}
}

这里的关键是在foreach循环中使用
dynamic
,将每个元素的类型分别从
Animal
更改为
Cat
Dog

有很多方法可以做到这一点。。。作为选项签出-可能使用
Piant((动态)动物)
和全套
Paint(Cat)
。。。重写。我不明白“两个对象的代码相同”是什么意思,你能展示你的绘画功能吗?@AlexeiLevenkov!有用的指针,谢谢。@user12341234“相同的代码”表示“相同的函数”,即没有动态调度。@user12341234我不确定您的问题是什么。如果您的绘制方法接受类型Animal,那么您的代码将按照您的方式工作。不幸的是,此解决方案似乎迫使我将我的
paint
代码与其他代码保持在同一位置。。。猫/狗类中的所有元素。
Paint
实际上属于每个特定类。否则,您将需要在“全局”绘制方法中使用一个不断增长的
if
select
语句来满足每种不同的可能动物。一个不断增长的if语句是一种解决方案,尽管它会强制模块紧密耦合。在其他语言中,动态分派或参数多态性是可行的替代方案。我想知道在C#中是否有另一种不需要巨大开关的方法。我不知道为什么在
Cat
类中使用所有
Cat
代码等等会是一个问题。你能详细介绍一下吗?你见过一只会画画的猫吗?猫知道如何睡觉和发出咕噜声,但我认为,画猫真的应该是画家的工作。