试图编程到C#中的抽象,但界面和类都没有真正起作用

发布于 2025-02-04 08:50:18 字数 1389 浏览 2 评论 0原文

我一直在尝试在我当前的项目上更加有意识地应用扎实的原则。使用接口来创建抽象并允许处理依赖注入以提供具体的类,这确实有助于解耦,从长远来看,(希望!)使其更加可维护。

但是,在这里和那里,我撞到了一堵墙,似乎界面和抽象类都没有起作用,原因是我想要定义实现的功能。

这意味着:

  • 接口将无法工作,因为我无法定义实现,并且显然不想重复所有实现类中的代码,
  • 因为我不能从多个类中派生

一些超级简单的代码来说明问题:

    public abstract class Vehicle
{
    public void MoveForward()
    {
        // Some code here
        // This implementation is always the same
    }

    public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}

public abstract class RadioSignalBroadcaster
{
    public void StartBroadcast()
    {
        // Some code here
        // This implementation is always the same
    }

    public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}

当然,我想做的是:

    public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
    // Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
    // bodys for the abstract methods

    public override void PerformUniqueAbility()
    {
        // class specific code here
    }

    public override void PerformUniqueBroadcastingAbility()
    {
        // class specific code here
    }
}

我不能这样做,因为错误:

错误CS1721类“ myNewClass”不能有多个基类:“车辆”和“ RadioSignalBroadcaster”

当然, 场景?

I've been trying to apply SOLID principles more consciously on my current project. Using interfaces to create the abstraction and allowing classes that are handling the dependency injection to provide the concretions has really helped with decoupling some of the code and (hopefully!) making it more maintainable in the long run.

However, here and there I'm hitting a bit of a wall where it seems neither interfaces nor abstract classes work for the reason that there are functions for which I want an implementation defined.

This means:

  • Interfaces will not work since I can't define an implementation and obviously don't want to repeat the code in all implementing classes
  • Abstract classes will not work because I cannot derive from multiple classes

Some super simple code to illustrate the problem:

    public abstract class Vehicle
{
    public void MoveForward()
    {
        // Some code here
        // This implementation is always the same
    }

    public abstract void PerformUniqueAbility(); // This is for the derived class to implement
}

public abstract class RadioSignalBroadcaster
{
    public void StartBroadcast()
    {
        // Some code here
        // This implementation is always the same
    }

    public abstract void PerformUniqueBroadcastingAbility(); // This is for the derived class to implement
}

Now of course what I'd like to do is this:

    public class MyNewClass: Vehicle, RadioSignalBroadcaster
{
    // Class that contains the implementations for both MoveForward() AND StartBroadcast() but also allows me to define
    // bodys for the abstract methods

    public override void PerformUniqueAbility()
    {
        // class specific code here
    }

    public override void PerformUniqueBroadcastingAbility()
    {
        // class specific code here
    }
}

Of course I cannot do this because of the error:

Error CS1721 Class 'MyNewClass' cannot have multiple base classes: 'Vehicle' and 'RadioSignalBroadcaster'

What's the best way to approach these scenarios?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌酱 2025-02-11 08:50:18

您可以使用具有默认实现的接口,这些接口在C#8中引入。然后,您可以从这些接口中得出。

以下是如何提供MoveForward()startBroadcast()方法的默认实现的示例:

public interface IVehicle
{
    void MoveForward()
    {
        // your code
    }
    void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
    void StartBroadcast()
    {
        // your code
    }
    void PerformUniqueBroadcastingAbility();
}

You could use interfaces with default implementations which were introduced in C# 8. Then you could derive from these interfaces.

Here's an example of how you could you provide default implementations for the MoveForward() and StartBroadcast() methods:

public interface IVehicle
{
    void MoveForward()
    {
        // your code
    }
    void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster
{
    void StartBroadcast()
    {
        // your code
    }
    void PerformUniqueBroadcastingAbility();
}
源来凯始玺欢你 2025-02-11 08:50:18

您不能继承超过1个类,但是可以继承多个接口。这是您想要的吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    internal class Program
    {
        static void Main(string[] args)
        {
            IVehicle vehicle = new Vehicle();
            IRadioBroadcaster broadcaster = new RadioBroadcaster();

            vehicle.MoveForward();
            vehicle.PerformUniqueAbility();
            broadcaster.StartBroadcast();
            broadcaster.PerformUniqueAbility();
        }
    }

    public interface IUniqueAbillity
    {
        void PerformUniqueAbility();
    }

    public interface IVehicle: IUniqueAbillity
    {
        void MoveForward();
    }

    public interface IRadioBroadcaster : IUniqueAbillity
    {
        void StartBroadcast();
    }

    public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
    {
        public void MoveForward()
        {
            // Move forward
        }

        public abstract void PerformUniqueAbility();

        public void StartBroadcast()
        {
            // Start broadcast
        }
    }

    public class Vehicle : RealWorldObject, IVehicle
    {
        public override void PerformUniqueAbility()
        {
            // Do something
        }
    }

    public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
    {
        public override void PerformUniqueAbility()
        {
            // Do something
        }
    }
}

You can't inherit more than 1 class but you can inherit more than one interface. Is this what you are looking for?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp3
{
    internal class Program
    {
        static void Main(string[] args)
        {
            IVehicle vehicle = new Vehicle();
            IRadioBroadcaster broadcaster = new RadioBroadcaster();

            vehicle.MoveForward();
            vehicle.PerformUniqueAbility();
            broadcaster.StartBroadcast();
            broadcaster.PerformUniqueAbility();
        }
    }

    public interface IUniqueAbillity
    {
        void PerformUniqueAbility();
    }

    public interface IVehicle: IUniqueAbillity
    {
        void MoveForward();
    }

    public interface IRadioBroadcaster : IUniqueAbillity
    {
        void StartBroadcast();
    }

    public abstract class RealWorldObject : IVehicle, IRadioBroadcaster
    {
        public void MoveForward()
        {
            // Move forward
        }

        public abstract void PerformUniqueAbility();

        public void StartBroadcast()
        {
            // Start broadcast
        }
    }

    public class Vehicle : RealWorldObject, IVehicle
    {
        public override void PerformUniqueAbility()
        {
            // Do something
        }
    }

    public class RadioBroadcaster : RealWorldObject, IRadioBroadcaster
    {
        public override void PerformUniqueAbility()
        {
            // Do something
        }
    }
}
烟火散人牵绊 2025-02-11 08:50:18

C#类只能从一个基类继承,但可以从任何数量的接口继承。

如果您的目标是将多个基本类继承为myNewClass,则可以将您的一个抽象类更改为从另一个中继承的:

public abstract class RadioSignalBroadcast : Vehicle
{
    // Implementation goes here
}

public class MyNewClass : RadioSignalBroacast
{
    // Implementation goes here
}

但是,正如您可以从此方法中看到的那样,它违反了单个责任原则现在为radioSignalBroadcast(现在myNewClass)有多个更改的理由(如果更改为perhat>车辆>车辆> radioSignalBroadcast逻辑)。任何基本类别发生的任何更改都会传播到从这些基类继承的所有其他类中,这可能是您所追求的也可能不是。

处理这些方案的最佳方法是什么?

这完全取决于您的应用程序的设计。要问自己的问题:

  • 您是否需要车辆radioSignAlBroadcast是抽象类,还是很容易成为接口?从实现的外观上看,您有几种方法要分享到派生的课程中,因此我了解您想将它们保留为基础课程,但要记住这一点。另外,请查看moveforwardstartBroadcast是否可以具有默认接口实现
  • myNewClass是否需要实现两个基类/接口?两个单独的课程不能更好吗?分开这样的课程有助于将每个班级集中到一个单一的责任。
  • 如果myNewClass不是真正的车辆radioSignalBroadcast(按照上一点)例如,这两个:
public class MyNewClass : Vehicle
{
    private readonly RadioSignalBroadcast radio;

    public MyNewClass(RadioSignalBroadcast radio)
    {
        this.radio = radio;
    }

    public void DoStuff()
    {
        // Do Stuff
        this.radio.PerformUniqueBroadcastingAbility();
    }

    // Implementation goes here
}

让我知道您是否要指出示例或更多要点。

C# classes can only inherit from one base class, but can inherit from any number of interfaces.

If your goal is to have multiple base classes being inherited to MyNewClass, you could change one of your abstract classes to inherit from the other, for example:

public abstract class RadioSignalBroadcast : Vehicle
{
    // Implementation goes here
}

public class MyNewClass : RadioSignalBroacast
{
    // Implementation goes here
}

However, as you can see from this approach, it violates Single Responsibility Principle as now RadioSignalBroadcast (and now MyNewClass) has more than one reason to change (if there's a change to Vehicle or RadioSignalBroadcast logic). Any change that happens to any of the base classes will propagate to all other classes which inherit from those base classes, which may or may not be what you're after.

What's the best way to approach these scenarios?

That entirely depends on the design of your application. Questions to ask yourself:

  • Do you require Vehicle and RadioSignalBroadcast to be abstract classes, or can it easily be an interface? By the looks of your implementation, you have a couple of methods which you want to share to your derived classes so I understand you wanting to keep them as base classes, but it's something to keep in mind. Also check out if the implementation of MoveForward and StartBroadcast can have a default interface implementation.
  • Does MyNewClass need to implement both base classes/interfaces? Couldn't two separate classes work out better? Separating out classes like this helps to focus each of the classes to have one single responsibility.
  • If MyNewClass is not truly a Vehicle or a RadioSignalBroadcast (as per the previous point), can this object be composed by a combination of either of the two, for example:
public class MyNewClass : Vehicle
{
    private readonly RadioSignalBroadcast radio;

    public MyNewClass(RadioSignalBroadcast radio)
    {
        this.radio = radio;
    }

    public void DoStuff()
    {
        // Do Stuff
        this.radio.PerformUniqueBroadcastingAbility();
    }

    // Implementation goes here
}

Let me know if you want example or more points to point out.

執念 2025-02-11 08:50:18

我认为乔纳斯(Jonas)为您提供了最好的答案,您可以使用默认的接口实现。但是,我保留帖子,因为它提供了信息,如何实现相同的效果,使用没有此语言功能的技术。

public abstract class Example : IExample 
{
    private readonly IVehicle vehicle;
    private readonly IRadioSignalBroadcaster;

    public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
    {
        this.vehicle = vehicle;
        this.radioSignalBroadcaster = radioSignalBroadcaster;
    }

    public void MoveForward() => vehicle.MoveForward();
    
    public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();

    public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();

    public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle 
{
    void MoveForward();
    void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster 
{
    void StartBroadcast();
    void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
    public void MoveForward()
    {
        // ...
    }

    public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle 
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
    public void PerformUniqueAbility() 
    {
        // ...
    } 
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
    public void StartBroadcast()
    {
        // ...
    }
    public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{   
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster 
{
    public void PerformUniqueBroadcastingAbility()
    {
        // ...
    }
}

您将创建其他类似的类:

public class CustomExample : Example, ICustomExample
{
    public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
    {
    }
}
public interface ICustomExample : IExample
{
}

I think Jonas gave you the best answer that you can use default interface implementations. However I keep my post, because it gives information, how to achieve same effect, using technology without this language feature.

public abstract class Example : IExample 
{
    private readonly IVehicle vehicle;
    private readonly IRadioSignalBroadcaster;

    public Example(IVehicle vehicle, IRadioSignalBroadcaster radioSignalBroadcaster)
    {
        this.vehicle = vehicle;
        this.radioSignalBroadcaster = radioSignalBroadcaster;
    }

    public void MoveForward() => vehicle.MoveForward();
    
    public void StartBroadcast() => radioSignalBroadcaster.StartBroadcast();

    public void PerformUniqueAbility() => vehicle.PerformUniqueAbility();

    public void PerformUniqueBroadcastingAbility() => radioSignalBroadcaster.PerformUniqueBroadcastingAbility();
}
public interface IExample : IVehicle, IRadioSignalBroadcaster
{
}
public interface IVehicle 
{
    void MoveForward();
    void PerformUniqueAbility();
}
public interface IRadioSignalBroadcaster 
{
    void StartBroadcast();
    void PerformUniqueBroadcastingAbility();
}
public abstract class Vehicle : IVehicle
{
    public void MoveForward()
    {
        // ...
    }

    public abstract void PerformUniqueAbility();
}
public interface ICustomVehicle : IVehicle 
{
}
public class CustomVehicle : Vehicle, ICustomVehicle
{
    public void PerformUniqueAbility() 
    {
        // ...
    } 
}
public abstract class RadioSignalBroadcaster : IRadioSignalBroadcaster
{
    public void StartBroadcast()
    {
        // ...
    }
    public abstract void PerformUniqueBroadcastingAbility();
}
public interface ICustomRadioSignalBroadcaster : IRadioSignalBroadcaster
{   
}
public class CustomRadioSignalBroadcaster : RadioSignalBroadcaster, ICustomRadioSignalBroadcaster 
{
    public void PerformUniqueBroadcastingAbility()
    {
        // ...
    }
}

You will create another classes like that:

public class CustomExample : Example, ICustomExample
{
    public CustomExample(ICustomVehicle customVehicle, ICustomRadioSignalBroadcaster customRadioSignalBroadcaster) : base(customVehicle, customRadioSignalBroadcaster)
    {
    }
}
public interface ICustomExample : IExample
{
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文