我正在使用class A
的实例。但是,我想用其他东西代替该类中的一种方法。我知道我可以编写一个不同的类并继承原始类,但是我不应该接触声明实例的代码部分。
我已经尝试使用覆盖该特定方法的方法来创建class B
,但是显然class A
中的线程已经在Main()
中启动了,因此无法正常工作。这是代码示例。感谢帮助!
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication2
{
class Program
{
/* The Original Class A that I am Not Supposed to Touch */
public class A
{
public A()
{
Thread thread_A = new Thread(Method1);
thread_A.Start();
}
public void Method1()
{
while(true)
{
Thread.Sleep(1000);
Method2();
}
}
/* I Want To Replace This Method with Something Else */
public virtual void Method2()
{
Console.WriteLine("This is in Class A");
}
}
/* Some Random Class I Created Myself that I Do Not Know If It Works */
public class B: A
{
/* The Method that I Want To Use */
public override void Method2()
{
Console.WriteLine("This is in Class B");
}
}
static void Main(string[] args)
{
/* I am not supposed to touch this either, it has to be an instance of A */
A instanceA = new A();
/* But I want the print result to be "This is in Class B" */
}
}
}
实际方案:Class A
用于通过网络套接字连续发送消息。 Class A
中有一种包装消息的方法。现在,我尝试使用其他格式包装邮件。因此,我要替换的方法位于Class A
中的执行中间。 Class A
发送消息的线程已经在我无法触摸的其他文件中启动了...
更新:如果我必须在A
中进行更改,是否有任何建议可以很好地覆盖该项目的方法?由于A
是由不同项目共享的通用文件。
答案 0 :(得分:0)
您所描述的问题在给定的约束内实际上是无法解决的。这不是告诉您如何去做自己想做的事情的答案,但是如果答案是不可能的话,那就是答案。但是我们仍然可以看看为什么这是不可能的,而我们可以做些什么。
您的代码会执行以下操作:
A instanceA = new A();
您不能更改此代码的行为,除非更改A
的行为或将此代码更改为不使用A
。这些约束之一必须改变。
这说明了耦合,在这种情况下,我们代码的不同部分相互绑定在一起,因此它们不能分开工作,并且我们不能更改一个部分而不更改其他内容。
这是一个示例,该示例不使用诸如A
和B
之类的名称,因为这样会使读取变得混乱。我并没有考虑太多-这只是说明问题的一个示例:
public class Stove
{
public void CookFood() { }
}
public class Chef
{
public void MakeFood()
{
var stove = new Stove();
stove.CookFood();
}
}
public class Parent
{
public void FeedChildren()
{
var stove = new Stove();
stove.CookFood();
}
}
没有Stove
,这些类都不可以工作。从某种意义上讲,您可以说Stove
是其中的一部分。如果更改Stove
,则实际上是在更改这两个类。如果不测试Stove
,也不能测试其中任何一个。
此外,由于这两个类都与Stove
耦合,因此它们也相互耦合。如果这些类之一需要Stove
来做不同的事情,则必须更改Stove
。结果将影响另一个类。这意味着对Chef
的更改可能会影响Parent
,反之亦然。
那是不可取的。它使我们的应用程序像一个大类一样工作,而不是拥有可以独立更改的较小部分。
消除这种耦合的一种常见方法是依赖抽象而不是具体的实现。我们可以将代码更改如下:
public interface IStove
{
void CookFood();
}
public class Chef
{
private readonly IStove _stove;
public Chef(IStove stove)
{
_stove = stove;
}
public void FeedChildren()
{
_stove.CookFood();
}
}
public class Parent
{
private readonly IStove _stove;
public Parent(IStove stove)
{
_stove = stove;
}
public void MakeFood()
{
_stove.CookFood();
}
}
现在,这两个类别都不依赖于具体的类别Stove
。两者都依赖于抽象-在这种情况下是接口-IStove
。
如果我有一个Stove
类,并且它同时满足Chef
和Parent
的需求,那么两者都可以使用它。但是,如果我需要另一个Stove
,例如Grill
或GiantPizzaOven
,该怎么办?现在,我可以创建一个实现IStove
的不同类。我不必更改现有的类。
现在没有类与IStove
的实现耦合,并且它们没有彼此耦合。我们可以独立更改Chef
,Parent
或Stove
,而不必强制更改其他类。
通过构造函数传递依赖项(如IStove
而不是让类创建它们(new Stove()
)的模式是依赖项注入。这是一种有用的模式,我强烈建议您阅读并尝试一下。最终,您可能会依赖它(没有双关语),但这超出了此答案的范围。
更多细节-您可能已经注意到,此答案中没有类继承。继承不是很糟糕,但继承可以。这是引入耦合的另一种方法。 IStove
的一种实现可以从另一种实现继承可能很有意义,但是也可能会引入其他问题。
那么我的建议是提防从继承开始 这类问题的解决方案。寻找不涉及继承的解决方案,仅在它具有明显意义时才使用它,如果您创建继承,请立即撤消它,并在混乱时立即寻找其他解决方案。
还有另一个细节:依靠像IStove
这样的接口可以减少问题,但是随着我们的代码变得越来越复杂,即使对于依赖同一抽象的不同类也可以将它们耦合在一起。 Interface Segregation Principle解决了这个问题。这只是雷达上的东西。