简体   繁体   English

如何使用接口和C#重写用抽象类编写的程序?

[英]How can I rewrite a program that was written with abstract class using interface and C#?

The Following C# program was written using abstract classes: 以下C#程序是使用抽象类编写的:

dBase.cs dBase.cs

using System;
namespace nmsD
{
    public abstract class dBase
    {
        protected string s_dBase { get; set; }
        protected abstract void methodX();
        public dBase()
        {
            Console.WriteLine("Construc_dBase");
        }
        public void Dq1 ()
        {
            string s = s_dBase;
            Console.WriteLine("Dq1" + " : " + s);
            methodX();
        }
    }
}

bBase.cs bBase.cs

using System;
using nmsD;
namespace nmsB 
{
    public abstract class bBase: dBase
    {

        public bBase()
        {
            s_dBase = "Prop.bBase.01";
            Console.WriteLine("Construc_bBase");
        }

        protected override void methodX(){
            Console.WriteLine("--->bBase_methodX (NOT SHOW)");
        }
    }

}

bRegular01 bRegular01

using System;
using nmsD;

namespace nmsB 
{
    public class bRegular01 : bBase
    {
        public bRegular01()
        {
            Console.WriteLine("Construc_bRegular01");
            //s_dBase = "Prop.bRegular02.02";
        }
        protected override void methodX()
        {
            Console.WriteLine("--->bRegular01_methodX (OK)");
        }
    }
}

bRegular02 bRegular02

using System;
using nmsD;

namespace nmsB 
{
    public class bRegular02 : bBase
    {
        public bRegular02()
        {
            Console.WriteLine("Construc_bRegular02");
            s_dBase = "Prop.bRegular02.02";
        }

        protected override void methodX()
        {
            Console.WriteLine("--->bRegular02_methodX (OK)");
        }
    }
}

Program.cs Program.cs中

using System;
using nmsB;

namespace nmsApp
{
    class Program
    {
        static void Main(string[] args)
        {
            nmsB.bRegular01 br01 = new nmsB.bRegular01();
            br01.Dq1();

            nmsB.bRegular02 br02 = new nmsB.bRegular02();
            br02.Dq1();

            Console.ReadKey();
        }
    }
}

The output is: 输出为:

    Construc_dBase
    Construc_bBase
    Construc_bRegular01
    Dq1 : Prop.bBase.01
    --->bRegular01_methodX (OK)
    Construc_dBase
    Construc_bBase
    Construc_bRegular02
    Dq1 : Prop.bRegular02.02
    --->bRegular02_methodX (OK)

The Question is: 问题是:

If possible, How can I do the same behavior using interfaces? 如果可能,如何使用接口执行相同的行为? What is the best approach to obtain this result? 获得此结果的最佳方法是什么? And why? 又为什么呢?

Edit: 编辑:

Thank you very much for the answers. 非常感谢您的回答。 Based in the first answers, and to better understanding, the main objective is: When the method methodX() is called from Dq1. 基于第一个答案,并且为了更好地理解,主要目标是:从Dq1调用方法methodX()时。 The output must show only the lines with: 输出必须仅显示带有以下内容的行:

--->bRegular01_methodX (OK)
or
--->bRegular02_methodX (OK)

and not must show de line: 并且不必显示de line:

--->bBase_methodX (NOT SHOW)

Abstract classes and interfaces aren't the same thing, so you can't have exactly the same behavior. 抽象类和接口不是同一回事,因此您不能具有完全相同的行为。

Interfaces are simply a contract that enforces that inheritors must have the stated methods and properties. 接口只是一个契约,它强制继承者必须具有声明的方法和属性。 An interface cannot have any implementation details. 接口不能包含任何实现详细信息。

Abstract classes are classes that just cannot be instantiated and thus have to be inherited from to make an actual object. 抽象类是无法实例化的类,因此必须从其继承以构成实际对象。 If you want functions in the base class that don't have to be explicitly overridden in child classes to work, then you cannot use an interface. 如果您希望不必在子类中显式重写基类中的函数即可正常工作,则不能使用接口。

The most glaring example of this is your constructor. 最明显的例子是您的构造函数。 Interfaces do not define implementations of methods, so something inheriting from an interface would be incapable of outputting your "Construc_dBase" lines without explicitly writing that Console.WriteLine statement in each of those classes' constructors. 接口没有定义方法的实现,因此从接口继承的内容将无法输出“ Construc_dBase”行,而无需在每个类的构造函数中显式编写该Console.WriteLine语句。

The closest you can get, with the code you provided, is to create the following interface: 使用提供的代码,最接近的是创建以下接口:

public interface ISomeInterface
{
    void methodX();
    string s_dBase { get; set; }
}

..And then have that interface inherited on each of your child classes (not the base class). ..然后在每个子类(而不是基类)上继承该接口。

First I'll explain why and then I'll explain why it's undesirable. 首先,我会解释原因,然后再解释为什么它是不可取的。

Why: 为什么:

Abstract methods are identical to interface methods, in their behavior. 抽象方法的行为与接口方法相同。 They define a signature with no implementation and demand that they be overridden or else the program will not compile. 它们定义了没有实现的签名,并要求覆盖它们,否则程序将无法编译。 The only part of your posted code that meets that template is the methodX function and the string property. 您发布的代码中唯一符合该模板的部分是methodX函数和string属性。 Therefore, you can pull them out into an interface. 因此,您可以将它们拉出到界面中。 Once you do so, though, you will have to implement them on each and every class that needs to be able to be interpreted as an ISomeInterface (ie needs to be able to call methodX without knowing the implementation). 但是,一旦这样做,您将必须在每个需要将其解释为ISomeInterface的类上实现它们(即,需要能够在不知道实现的情况下调用methodX)。 Inheriting the interface on your base class means the base class would have to actually implement them yourself, which looks like it's what you don't want to do. 在基类上继承接口意味着基类必须自己实际实现它们,这似乎是您不想执行的操作。

Why is it undesirable? 为什么不理想?

You are now responsible for not only inheriting the base class, but now also an interface, to ensure complete interoperability. 现在,您不仅要继承基类,而且还要继承一个接口,以确保完全的互操作性。 If that's not too onerous for you, then by all means do that, but it seems pretty unnecessary. 如果那对您来说不太麻烦,那么请务必这样做,但这似乎是不必要的。 Also, there's no longer a guarantee that a nmsD is also an ISomeInterface, unless you explicitly provide an implementation of methodX and s_dBase on the nmsD class, which, again, seems like it's exactly what you don't want to do. 另外,不再保证nmsD也是ISomeInterface,除非您在nmsD类上显式提供methodX和s_dBase的实现,这又似乎完全是您不想执行的操作。 Additionally, interfaces do not define accessibility constraints (public, private, protectec, internal), whereas abstract classes can. 此外,接口没有定义可访问性约束(公共,私有,protectec,内部),而抽象类可以。

Why is it debatable? 为什么有争议?

There are different ways of doing things, and each has its benefits and drawbacks. 办事方式不同,每种都有其优点和缺点。 Abstract classes tie you down to a single base implementation, while interfaces do not. 抽象类将您限制在单个基本实现上,而接口则没有。 Interfaces can't provide implementation details at all, while abstract classes can. 接口根本无法提供实现细节,而抽象类则可以。

This can get into a very off-topic and very drawn-out discussion, though, so I'll cut it off here. 但是,这可能会引起非常离题和非常冗长的讨论,因此我在这里将其截断。

Interfaces can define method and property signatures, but have no implementation. 接口可以定义方法和属性签名,但是没有实现。 You can change your abstract classes' signatures to interfaces, moving all the implementation to inherited concrete classes. 您可以将抽象类的签名更改为接口,将所有实现都移到继承的具体类上。

Abstract classes and Interfaces provide solutions to two different problems, one isn't going to be equally as good as the other for every given scenario. 抽象类和接口为两个不同的问题提供了解决方案,对于每种给定方案,一个问题都不会像另一个问题一样好。 If you need more help, provide more information. 如果您需要更多帮助,请提供更多信息。

Here is an implementation of the classes provided, using interfaces, and the program's output. 这是使用接口提供的类的实现,以及程序的输出。 I tried not to mess with the naming of the classes. 我尽力不干扰类的命名。

Output: 输出:

Construc_bRegular01
Dq1: Prop.bRegular01.01
--->bRegular01_methodX (OK)
Construc_bRegular02
Dq1: Prop.bRegular02.02
--->bRegular02_methodX (OK)

Code: 码:

namespace nmsD
{
    public interface IdBase
    {
        string s_dBase { get; set; }
        void methodX( );
        void Dq1( );
    }

}

namespace nmsB
{
    using nmsD;

    public class bRegular01 : IdBase
    {
        public bRegular01( )
        {
            Console.WriteLine( "Construc_bRegular01" );
            s_dBase = "Prop.bRegular01.01";
        }

        public string s_dBase { get; set; }

        public void methodX( )
        {
            Console.WriteLine( "--->bRegular01_methodX (OK)" );
        }

        public void Dq1( )
        {
            Console.WriteLine( "Dq1: {0}", s_dBase );
            methodX( );
        }
    }

    public class bRegular02 : IdBase
    {
        public bRegular02( )
        {
            Console.WriteLine( "Construc_bRegular02" );
            s_dBase = "Prop.bRegular02.02";
        }

        public string s_dBase { get; set; }

        public void methodX( )
        {
            Console.WriteLine( "--->bRegular02_methodX (OK)" );
        }

        public void Dq1( )
        {
            Console.WriteLine( "Dq1: {0}", s_dBase );
            methodX( );
        }
    }
}


namespace nmsApp
{
    internal class Program
    {
        private static void Main( string[ ] args )
        {
            nmsB.bRegular01 br01 = new nmsB.bRegular01( );
            br01.Dq1( );

            nmsB.bRegular02 br02 = new nmsB.bRegular02( );
            br02.Dq1( );

            Console.ReadKey( );
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM