将同一个类与一种方法一起使用

时间:2019-08-29 14:13:22

标签: c# overriding

我正在使用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是由不同项目共享的通用文件。

1 个答案:

答案 0 :(得分:0)

您所描述的问题在给定的约束内实际上是无法解决的。这不是告诉您如何去做自己想做的事情的答案,但是如果答案是不可能的话,那就是答案。但是我们仍然可以看看为什么这是不可能的,而我们可以做些什么。

您的代码会执行以下操作:

A instanceA = new A();

您不能更改此代码的行为,除非更改A的行为或将此代码更改为使用A。这些约束之一必须改变。

这说明了耦合,在这种情况下,我们代码的不同部分相互绑定在一起,因此它们不能分开工作,并且我们不能更改一个部分而不更改其他内容。

这是一个示例,该示例不使用诸如AB之类的名称,因为这样会使读取变得混乱。我并没有考虑太多-这只是说明问题的一个示例:

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类,并且它同时满足ChefParent的需求,那么两者都可以使用它。但是,如果我需要另一个Stove,例如GrillGiantPizzaOven,该怎么办?现在,我可以创建一个实现IStove的不同类。我不必更改现有的类。

现在没有类与IStove的实现耦合,并且它们没有彼此耦合。我们可以独立更改ChefParentStove,而不必强制更改其他类。


通过构造函数传递依赖项(如IStove而不是让类创建它们(new Stove())的模式是依赖项注入。这是一种有用的模式,我强烈建议您阅读并尝试一下。最终,您可能会依赖它(没有双关语),但这超出了此答案的范围。


更多细节-您可能已经注意到,此答案中没有类继承。继承不是很糟糕,但继承可以。这是引入耦合的另一种方法。 IStove的一种实现可以从另一种实现继承可能很有意义,但是也可能会引入其他问题。

那么我的建议是提防从继承开始 这类问题的解决方案。寻找不涉及继承的解决方案,仅在它具有明显意义时才使用它,如果您创建继承,请立即撤消它,并在混乱时立即寻找其他解决方案。


还有另一个细节:依靠像IStove这样的接口可以减少问题,但是随着我们的代码变得越来越复杂,即使对于依赖同一抽象的不同类也可以将它们耦合在一起。 Interface Segregation Principle解决了这个问题。这只是雷达上的东西。