了解 C# 中的组合
Understanding composition in C#
我想更好地理解组合而不是继承。我看了一些教程,这些教程很好地解释了这些概念,但使用的是我更熟悉的语言,例如 Python。但是,我目前正在学习 C#,并且正在努力实施我在该主题上学到的知识,想知道是否有人可以提供帮助。这是我的代码:
using System;
namespace Composition
{
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot(new Dog(),new Robot());
steven.Bark();
}
}
class Dog
{
public void Bark()
{
Console.WriteLine("Woof");
}
}
class Robot
{
public void Move()
{
Console.WriteLine("I'm moving!");
}
}
class CleanRobot
{
public void Clean()
{
Console.WriteLine("Just keep dusting, just keep dusting");
}
}
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot)
{
this.o1 = dog;
this.o2 = robot;
}
}
}
基本上,我有一个 Dog
可以 bark
,一个 Robot
可以 move
和一个 CleanRobot
可以 clean
.我想创建一个可以移动、吠叫和清洁的 SuperBot,并使用合成来实现这一目标。
我有两个主要问题:
以上是我到目前为止编写的代码,但它不允许我在我的 SuperBot
对象上调用 Bark
方法,正如它所说 SuperBot
class 不包含此方法。
如果我的 Dog
class 也可以 Eat()
但我不想将此方法用于我的 SuperBot
class?
非常感谢任何帮助 - 努力解决这个问题!
更新 - 尝试使用接口
using System;
namespace Composition
{
public interface ICanBark
{
string Bark();
}
public interface ICanMove
{
string Move();
}
public interface ICanClean
{
string Clean();
}
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot();
steven.Bark();
}
}
class Dog : ICanBark
{
public string Bark()
{
return "Woof";
}
}
class Robot : ICanMove
{
public string Move()
{
return "I'm moving";
}
}
class CleanRobot : ICanClean
{
public string Clean()
{
return "Just keep dusting, just keep dusting";
}
}
class SuperBot : ICanBark, ICanMove, ICanClean
{
public string Bark()
{
return "Barking";
}
}
}
我认为 SuperBot 是一个 aggregration type object composition,但我不是 100% 相信那些深入理论领域的术语。
你的描述听起来像是你想做多重继承。不幸的是,那个导致 Diamond Problem。这是 .NET 开发人员想要避免的众多问题之一。于是他们宣布:"Single Inheitance only"。 (注意C#完全支持Multiple Inheritance,但这里Framework规则更重要)
.NET 确实有一些类似于多重继承的东西:Interfaces。没有更好的术语,接口是 "more abstract then a abstract class"。接口不是继承的,而是实现的。由于它们不携带任何代码,您可以实现任意数量的接口,而不必冒可怕的死亡钻石风险。
在您的情况下,您可能需要接口 ICanBark、ICanMove 和 ICanClean。具体的 Dog、Robot 和 Cleaner 类 实现了其中之一。 SuperBot 全部 3.
在您的示例中使用合成时,不幸的是,您还必须在合成中实现暴露的方法 class:
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot, CleanRobot cleanRobot)
{
this.o1 = dog;
this.o2 = robot;
this.o3 = cleanRobot;
}
public void Bark() => o1.Bark();
public void Move() => o2.Move();
public void Clean() => o3.Clean();
}
这将解决您的编译器错误。此外,如果您向 Dog
、Robot
或 CleanRobot
添加更多方法,它们将不会影响 SuperBot
提供的内容,即如果 Dog
具有方法 Eat()
, SuperBot
不会有这个方法,除非你也加上它。
如果您将 SuperBot
建模为实际上由 Dog
、Robot
和 CleanRobot
组成,那么从概念上讲,您可以像这样使用组合。 SuperBot
然后用它的 Dog
来吠叫,用它的 CleanRobot
来清洁。
编辑(来自评论):
如果你想要一个调用Bark
的函数
public void GoodBoy(Dog dog)
{
dog.Bark();
}
您不能将 SuperRobot
传递给此方法。在这种情况下,您需要 Dog
和 SuperRobot
的通用接口,其中包含 Bark
方法。
我想更好地理解组合而不是继承。我看了一些教程,这些教程很好地解释了这些概念,但使用的是我更熟悉的语言,例如 Python。但是,我目前正在学习 C#,并且正在努力实施我在该主题上学到的知识,想知道是否有人可以提供帮助。这是我的代码:
using System;
namespace Composition
{
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot(new Dog(),new Robot());
steven.Bark();
}
}
class Dog
{
public void Bark()
{
Console.WriteLine("Woof");
}
}
class Robot
{
public void Move()
{
Console.WriteLine("I'm moving!");
}
}
class CleanRobot
{
public void Clean()
{
Console.WriteLine("Just keep dusting, just keep dusting");
}
}
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot)
{
this.o1 = dog;
this.o2 = robot;
}
}
}
基本上,我有一个 Dog
可以 bark
,一个 Robot
可以 move
和一个 CleanRobot
可以 clean
.我想创建一个可以移动、吠叫和清洁的 SuperBot,并使用合成来实现这一目标。
我有两个主要问题:
以上是我到目前为止编写的代码,但它不允许我在我的
SuperBot
对象上调用Bark
方法,正如它所说SuperBot
class 不包含此方法。如果我的
Dog
class 也可以Eat()
但我不想将此方法用于我的SuperBot
class?
非常感谢任何帮助 - 努力解决这个问题!
更新 - 尝试使用接口
using System;
namespace Composition
{
public interface ICanBark
{
string Bark();
}
public interface ICanMove
{
string Move();
}
public interface ICanClean
{
string Clean();
}
class Program
{
static void Main(string[] args)
{
SuperBot steven = new SuperBot();
steven.Bark();
}
}
class Dog : ICanBark
{
public string Bark()
{
return "Woof";
}
}
class Robot : ICanMove
{
public string Move()
{
return "I'm moving";
}
}
class CleanRobot : ICanClean
{
public string Clean()
{
return "Just keep dusting, just keep dusting";
}
}
class SuperBot : ICanBark, ICanMove, ICanClean
{
public string Bark()
{
return "Barking";
}
}
}
我认为 SuperBot 是一个 aggregration type object composition,但我不是 100% 相信那些深入理论领域的术语。
你的描述听起来像是你想做多重继承。不幸的是,那个导致 Diamond Problem。这是 .NET 开发人员想要避免的众多问题之一。于是他们宣布:"Single Inheitance only"。 (注意C#完全支持Multiple Inheritance,但这里Framework规则更重要)
.NET 确实有一些类似于多重继承的东西:Interfaces。没有更好的术语,接口是 "more abstract then a abstract class"。接口不是继承的,而是实现的。由于它们不携带任何代码,您可以实现任意数量的接口,而不必冒可怕的死亡钻石风险。
在您的情况下,您可能需要接口 ICanBark、ICanMove 和 ICanClean。具体的 Dog、Robot 和 Cleaner 类 实现了其中之一。 SuperBot 全部 3.
在您的示例中使用合成时,不幸的是,您还必须在合成中实现暴露的方法 class:
class SuperBot
{
// can clean, move and bark
public Dog o1;
public Robot o2;
public CleanRobot o3;
public SuperBot(Dog dog, Robot robot, CleanRobot cleanRobot)
{
this.o1 = dog;
this.o2 = robot;
this.o3 = cleanRobot;
}
public void Bark() => o1.Bark();
public void Move() => o2.Move();
public void Clean() => o3.Clean();
}
这将解决您的编译器错误。此外,如果您向 Dog
、Robot
或 CleanRobot
添加更多方法,它们将不会影响 SuperBot
提供的内容,即如果 Dog
具有方法 Eat()
, SuperBot
不会有这个方法,除非你也加上它。
如果您将 SuperBot
建模为实际上由 Dog
、Robot
和 CleanRobot
组成,那么从概念上讲,您可以像这样使用组合。 SuperBot
然后用它的 Dog
来吠叫,用它的 CleanRobot
来清洁。
编辑(来自评论):
如果你想要一个调用Bark
public void GoodBoy(Dog dog)
{
dog.Bark();
}
您不能将 SuperRobot
传递给此方法。在这种情况下,您需要 Dog
和 SuperRobot
的通用接口,其中包含 Bark
方法。