【问题标题】:Should this code have been a Base class instead of an Interface?这段代码应该是基类而不是接口吗?
【发布时间】:2023-03-22 05:37:01
【问题描述】:

接口与基类对我来说仍然是一个相当灰色的领域。我正在阅读一本关于 ASP.NET 3.5 企业开发的书,作者指出所有表都将具有以下字段:

InsertDate
InsertENTUserAccountId
UpdateDate
UpdateENTUserAccountId
Version

如果这是我编写上述要求的代码,我将创建一个包含这些字段的基本业务对象类,并且所有业务对象都将从它继承。但是,作者将它们创建为接口。馊主意?好主意?没关系?

更新

有一个实现这个接口的基类。似乎所有业务对象都将从基础继承。但即便如此,我还是会把这个接口放在基类中......?

【问题讨论】:

标签: c# asp.net oop


【解决方案1】:

嗯,接口通常是首选,因为它允许更大的灵活性和抽象性 - 但您可以通过让您的 abstract 基类实现接口来实现这两者。然后 95% 的时间您使用基类,当您需要不同的东西时,您只需使用接口。

只是不要触碰业务代码中的基类……只触碰界面。基类只是一个实现细节。

【讨论】:

    【解决方案2】:

    通过使用接口,您需要在实现该接口的所有类中实现所有这些属性。如果所有的实现都是相同的,那么这就是很多重复的代码。这可以通过让基类实现接口来缓解。

    通过使用基类,您可以在所有子类之间共享相同的实现。如果您需要对其他内容进行子类化,就会出现问题,因为 .NET 不允许多重继承。这样,您将不得不直接实现接口(可能使用组合)。

    【讨论】:

    • 好点,我将在原始帖子中添加更多上下文以清除此问题...
    • 接口不是多重继承的方式。拥有“has-a”关系(uml 中的组合)比实现多个接口只是为了拥有“多重继承”(“is-a”关系)更好。
    • 我看到我的回答可能会令人困惑。我没有说您使用接口进行多重继承。我说你不能子类化两个类,因为没有多重继承,并且“解决方法”需要使用接口。会澄清的。
    【解决方案3】:

    他保证他们在那里,但没有提前定义他们必须做什么。与直接继承相比,这些也可能与行为更相关。如果它们是行为关系而不是直接继承为 is-a 关系,那么接口是最好的,也许是唯一的方法。

    编辑:如果您考虑一下,并非所有表都具有相同的数据,但它们都必须对帐户做一些事情。这是行为关系,而不是 is-a 关系,因此是接口。

    【讨论】:

      【解决方案4】:

      为了定义类的通用“契约”,我通常会使用接口。然后我可能会定义一个抽象基类,它提供一些默认实现并履行接口定义的全部或部分“合同”。如果每个类的实现都不同,我可能会省略抽象基类。不过,我通常不会定义没有接口的抽象基类。我的实体也可能实现多个接口。

      【讨论】:

        【解决方案5】:

        有点像其他人所说的,但我的想法很简单:

        • 如果您希望它从外部看起来相同,请将其设为界面。
        • 如果您希望其内部相同,请将其设为基类。
        • 您可能希望两者都做。

        【讨论】:

          【解决方案6】:

          我认为查看界面的最佳方式是: “将由实现该接口的类提供的列表服务”。 一个例子是 ISwitchable,所有实现这个接口的类都提供了一种切换方式(在接口中定义)。 ISwitchable 的实现可以是一个按钮。

          另一方面,基类/子类关系可以描述为: 子类是基类的特化。 所以如果你有一个宠物作为基类,你可以让狗从基类派生,因为它是宠物的特化。你不能说狗提供宠物服务。在这个例子中狗类可以实现 IBrag 接口。

          我不同意这里的某些答案,即“何时”某些东西应该是接口或基类。它是建模过程的一部分,因此它取决于业务对象和上下文,是否应该是接口或基类。

          【讨论】:

            【解决方案7】:

            如果你永远不需要实例化它,那么它就是一个接口,否则它就是一个基类。

            【讨论】:

            • “如果你永远不需要实例化它,那么它就是一个接口”——或者一个abstract基类...
            • 但是你不能实例化一个抽象类......你可以使用派生类的实例作为基类的实例,但你也可以使用接口的实例-实现者作为接口实例。
            • 这就是为什么抽象基类是接口的原因——唯一的区别是由不能正确支持 OOP 的语言/实现引起的实现细节,并迫使您跳过箍以避免陷阱
            【解决方案8】:

            我认为你应该在接口中考虑一个类型应该实现的行为,而不必考虑这个类型是什么。它们应该是轻量级的,并允许扩展您的对象和第三方对象。基类与继承它的类家族有更多的关系,因此应该与它有一些语义关系。而且,当然,您可以同时使用两者,这是一种可能性。您应该有一个接口 ILoggable (我猜您正在使用该信息进行日志记录)或其他任何东西,并且基于您的系统架构,您可以拥有一个或多个实现此接口的基类,以使您免于编写重复代码,例如,一个将实现 ILoggable 的 AbstractPerson 和一个 Person 对象继承它,这种方法在未来是可扩展的,很容易在别人的代码中实现,并且给你一个灵活性。

            【讨论】:

              【解决方案9】:

              仅将其创建为接口,由于所有代码重复,这是一个坏主意,在这种情况下,最合适的做法是两者都做,你可以有一个基类和一个基类所有其他表接口都继承自的接口

              IBaseInterface {
               //basic fields
              }
              
              ITable1Interface : IBaseInterface
              
              BaseClass : IBaseInterface {
                //basic fields implementation
              }
              
              Table1Class : BaseClass...
              

              【讨论】:

                猜你喜欢
                • 2023-03-29
                • 2021-05-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-12-01
                • 1970-01-01
                • 2011-06-06
                • 1970-01-01
                相关资源
                最近更新 更多