从类或抽象类继承

时间:2022-03-12 07:49:48

If you have several classes where you want them to inherit from a base class for common functionality, should you implement the base class using a class or an abstract class?

如果你有几个类希望它们从基类继承以获得通用功能,那么你应该使用类或抽象类来实现基类吗?

11 个解决方案

#1


37  

That depends, if you never want to be able to instantiate the base class then make it abstract. Otherwise leave it as a normal class.

这取决于,如果您永远不希望能够实例化基类,那么将其抽象化。否则将其保留为普通班级。

#2


16  

If the base class ought not to be instantiated then make it an abstract class - if the base class needs to be instantiated then don't make it abstract.

如果基类不应该被实例化,那么使它成为一个抽象类 - 如果基类需要实例化,那么不要使它抽象化。

In this example it makes sense to make the base class abstract as the base class does not have any concrete meaning:

在这个例子中,使基类抽象是有意义的,因为基类没有任何具体含义:

abstract class WritingImplement
{
    public abstract void Write();
}

class Pencil : WritingImplement
{
    public override void Write() { }
}

However in this next example you can see how the base class does have concrete meaning:

但是在下一个示例中,您可以看到基类如何具有具体含义:

class Dog
{
    public virtual void Bark() { }
}

class GoldenRetriever : Dog
{
    public override void Bark() { }
}

It is all pretty subjective really - you ought to be able to make a pretty good judgment call based on the needs of your particular domain.

这一切都非常主观 - 你应该能够根据你的特定领域的需求做出相当不错的判断。

#3


6  

It depends, does it make sense for the base class in question to exist on it's own without being derived from? If the answer is yes, then it should be a regular class, otherwise, it should be an abstract class.

这取决于,有问题的基类是否有意义存在于它自己而不是从中派生出来?如果答案是肯定的,那么它应该是一个普通的类,否则,它应该是一个抽象类。

#4


3  

Think of it like a bank account:

可以把它想象成一个银行账户:

You can make a generic abstract base account called "Account", this holds basic information such as customer details.

您可以创建一个名为“帐户”的通用抽象基本帐户,它包含客户详细信息等基本信息。

You can then create two derived classes called "SavingAccount" or "DebitAccount" which can have their own specific behaviour whilst benefiting from the base class behaviour.

然后,您可以创建两个名为“SavingAccount”或“DebitAccount”的派生类,这些类可以具有自己的特定行为,同时受益于基类行为。

This is a situation where the customer must have either a Savings Account or a Debit Account, a generic "Account" is not allowed as it is not very popular in the real world to have just an account of no description.

在这种情况下,客户必须拥有储蓄账户或借记账户,不允许使用通用的“账户”,因为在现实世界中仅仅拥有无描述的帐户并不是很受欢迎。

If you can create a similar scenario for your needs, abstract is the way to go.

如果您可以根据需要创建类似的场景,那么抽象是可行的方法。

#5


3  

I suggest:

我建议:

  • Make an interface.
  • 建立一个界面。
  • Implement the interface in your base class.
  • 在基类中实现接口。
  • Make the base class a real class, not abstract (see below for why).
  • 使基类成为一个真正的类,而不是抽象的(见下面的原因)。

The reason I prefer real classes instead of abstract classes is that abstract classes cannot be instantiated, which limits future options unnecessarily. For example, later on I may need the state and methods provided by the base class but cannot inherit and do not need to implement the interface; if the base class is abstract I am out of luck, but if the base class is a regular class then I can create an instance of the base class and hold it as a component of my other class, and delegate to the instance to reuse the state/methods provided.

我更喜欢真正的类而不是抽象类的原因是抽象类无法实例化,这会不必要地限制未来的选项。例如,稍后我可能需要基类提供的状态和方法但不能继承而不需要实现接口;如果基类是抽象的我运气不好,但如果基类是常规类,那么我可以创建基类的实例并将其作为我的其他类的一个组件,并委托给实例重用提供的州/方法。

Yes this does not happen often, but the point is: making the base class abstract prevents this kind of reuse/solution, when there is no reason to do so.

是的,这不会经常发生,但关键是:当没有理由这样做时,使基类抽象可以防止这种重用/解决方案。

Now, if instantiating the base class would somehow be dangerous, then make it abstract - or preferably make it less dangerous, if possible ;-)

现在,如果实例化基类会以某种方式危险,那么将其抽象化 - 或者最好使其不那么危险,如果可能的话;-)

#6


1  

Abstract classes are for partially implemented classes.

抽象类用于部分实现的类。

By itself doesn't make sense to have an instance of an abstract class, it needs to be derived. If you would like to be able to create the base class it cannot be abstract.

拥有一个抽象类的实例本身没有意义,它需要派生。如果您希望能够创建基类,则它不能是抽象的。

I like to think of abstract classes as interfaces which have some members pre-defined since they are common to all sub-classes.

我喜欢将抽象类视为具有一些预定义成员的接口,因为它们对所有子类都是通用的。

#7


1  

Think of this a different way

想一想这种方式

Is my a base class a complete object on it's own?

我的基类是否是它自己的完整对象?

If the answer is no, then make it abstract. If it's yes then you likely want to make it a concrete class.

如果答案是否定的,则将其抽象化。如果是,那么你可能想把它变成一个具体的类。

#8


0  

I would say if you are not planning on calling the base class by itself, the then you should define it as an abstract class.

我想说如果你不打算单独调用基类,那么你应该将它定义为抽象类。

#9


0  

The depends on whether you want the base class to be implemented on its own or not.

这取决于您是否希望基类自行实现。

As an abstract class, you can't make objects from it.

作为抽象类,您无法从中创建对象。

#10


0  

Abstract classes are great for predefined functionality, for example - when know the minimum exact behaviour a class should expose but not what data it should use to do it or the exact implementation.

抽象类非常适合预定义的功能,例如 - 当知道类应该暴露的最小确切行为但不知道它应该使用什么数据来执行它或确切的实现。

abstract class ADataAccess
{
    abstract public void Save();
}

Normal (non abstract) classes can be great for similar things but you have to know the implementation specifics to be able to write them.

普通(非抽象)类可以用于类似的事情,但你必须知道能够编写它们的实现细节。

public class DataAccess
{
    public void Save()
    {
        if ( _is_new )
        {
            Insert();
        }
        else if ( _is_modified )
        {
            Update();
        }
    }
}

Also, you could use interfaces (individually or on classes, whether abstract or not) to define the same sort of prototype definition.

此外,您可以使用接口(单独或在类上,无论是否抽象)来定义相同类型的原型定义。

interface ISaveable
{
    void Save();
    void Insert();
    void Update();
}

class UserAccount : ISavable
{
    void ISavable.Save() { ... }
    void ISavable.Insert() { ... }
    void ISavable.Update() { ... }
}

Yet another option may be using generics

另一种选择可能是使用泛型

class GenDataAccess<T>
{
    public void Save()
    {
        ...
    }
}

All these methods can be used to define a certain prototype for classes to work with. Ways to make sure that code A can talk to code B. And of course you can mix and match all of the above to your liking. There is no definite right way but I like defining interfaces and abstract classes, then referring to the interfaces. That way eliminates some of the thought requirements for "plumbing" in higher level classes while keeping the maximum flexibility. (having interfaces takes away the requirement of using the abstract base class, but leaves it as an option).

所有这些方法都可用于为要使用的类定义某个原型。确保代码A可以与代码B通信的方法。当然,您可以根据自己的喜好混合和匹配以上所有内容。没有明确的正确方法,但我喜欢定义接口和抽象类,然后引用接口。这样就消除了更高级别的“管道”的一些思想要求,同时保持了最大的灵活性。 (让接口消除了使用抽象基类的要求,但将其留作选项)。

#11


-7  

I think a lot of you should resit basic OO classes again.

我想很多人应该再次重新启用基本的OO课程。

The basic underlying principle in OOA/OOD is to abstract abstract abstract, until you can't abstract no more. If what your looking at is an abstraction then so be it, thats what your OOA/OOD already told you. However if you sitting there wondering whether "code" should be abstract or not then you obviously don't know what the term means and should go learn basic OOA/OOD/OOP again :-)

OOA / OOD的基本原理是抽象抽象抽象,直到你不能抽象为止。如果你所看到的是一个抽象,那就这样吧,那就是你的OOA / OOD告诉你的。但是,如果你坐在那里想知道“代码”是否应该是抽象的,那么你显然不知道该术语的含义,应该再次学习基本的OOA / OOD / OOP :-)

More to the point you should learn Design Patterns and Harmonic Theory, this will help with your OO designs immensely!

更重要的是,您应该学习设计模式和谐波理论,这将极大地帮助您的OO设计!

#1


37  

That depends, if you never want to be able to instantiate the base class then make it abstract. Otherwise leave it as a normal class.

这取决于,如果您永远不希望能够实例化基类,那么将其抽象化。否则将其保留为普通班级。

#2


16  

If the base class ought not to be instantiated then make it an abstract class - if the base class needs to be instantiated then don't make it abstract.

如果基类不应该被实例化,那么使它成为一个抽象类 - 如果基类需要实例化,那么不要使它抽象化。

In this example it makes sense to make the base class abstract as the base class does not have any concrete meaning:

在这个例子中,使基类抽象是有意义的,因为基类没有任何具体含义:

abstract class WritingImplement
{
    public abstract void Write();
}

class Pencil : WritingImplement
{
    public override void Write() { }
}

However in this next example you can see how the base class does have concrete meaning:

但是在下一个示例中,您可以看到基类如何具有具体含义:

class Dog
{
    public virtual void Bark() { }
}

class GoldenRetriever : Dog
{
    public override void Bark() { }
}

It is all pretty subjective really - you ought to be able to make a pretty good judgment call based on the needs of your particular domain.

这一切都非常主观 - 你应该能够根据你的特定领域的需求做出相当不错的判断。

#3


6  

It depends, does it make sense for the base class in question to exist on it's own without being derived from? If the answer is yes, then it should be a regular class, otherwise, it should be an abstract class.

这取决于,有问题的基类是否有意义存在于它自己而不是从中派生出来?如果答案是肯定的,那么它应该是一个普通的类,否则,它应该是一个抽象类。

#4


3  

Think of it like a bank account:

可以把它想象成一个银行账户:

You can make a generic abstract base account called "Account", this holds basic information such as customer details.

您可以创建一个名为“帐户”的通用抽象基本帐户,它包含客户详细信息等基本信息。

You can then create two derived classes called "SavingAccount" or "DebitAccount" which can have their own specific behaviour whilst benefiting from the base class behaviour.

然后,您可以创建两个名为“SavingAccount”或“DebitAccount”的派生类,这些类可以具有自己的特定行为,同时受益于基类行为。

This is a situation where the customer must have either a Savings Account or a Debit Account, a generic "Account" is not allowed as it is not very popular in the real world to have just an account of no description.

在这种情况下,客户必须拥有储蓄账户或借记账户,不允许使用通用的“账户”,因为在现实世界中仅仅拥有无描述的帐户并不是很受欢迎。

If you can create a similar scenario for your needs, abstract is the way to go.

如果您可以根据需要创建类似的场景,那么抽象是可行的方法。

#5


3  

I suggest:

我建议:

  • Make an interface.
  • 建立一个界面。
  • Implement the interface in your base class.
  • 在基类中实现接口。
  • Make the base class a real class, not abstract (see below for why).
  • 使基类成为一个真正的类,而不是抽象的(见下面的原因)。

The reason I prefer real classes instead of abstract classes is that abstract classes cannot be instantiated, which limits future options unnecessarily. For example, later on I may need the state and methods provided by the base class but cannot inherit and do not need to implement the interface; if the base class is abstract I am out of luck, but if the base class is a regular class then I can create an instance of the base class and hold it as a component of my other class, and delegate to the instance to reuse the state/methods provided.

我更喜欢真正的类而不是抽象类的原因是抽象类无法实例化,这会不必要地限制未来的选项。例如,稍后我可能需要基类提供的状态和方法但不能继承而不需要实现接口;如果基类是抽象的我运气不好,但如果基类是常规类,那么我可以创建基类的实例并将其作为我的其他类的一个组件,并委托给实例重用提供的州/方法。

Yes this does not happen often, but the point is: making the base class abstract prevents this kind of reuse/solution, when there is no reason to do so.

是的,这不会经常发生,但关键是:当没有理由这样做时,使基类抽象可以防止这种重用/解决方案。

Now, if instantiating the base class would somehow be dangerous, then make it abstract - or preferably make it less dangerous, if possible ;-)

现在,如果实例化基类会以某种方式危险,那么将其抽象化 - 或者最好使其不那么危险,如果可能的话;-)

#6


1  

Abstract classes are for partially implemented classes.

抽象类用于部分实现的类。

By itself doesn't make sense to have an instance of an abstract class, it needs to be derived. If you would like to be able to create the base class it cannot be abstract.

拥有一个抽象类的实例本身没有意义,它需要派生。如果您希望能够创建基类,则它不能是抽象的。

I like to think of abstract classes as interfaces which have some members pre-defined since they are common to all sub-classes.

我喜欢将抽象类视为具有一些预定义成员的接口,因为它们对所有子类都是通用的。

#7


1  

Think of this a different way

想一想这种方式

Is my a base class a complete object on it's own?

我的基类是否是它自己的完整对象?

If the answer is no, then make it abstract. If it's yes then you likely want to make it a concrete class.

如果答案是否定的,则将其抽象化。如果是,那么你可能想把它变成一个具体的类。

#8


0  

I would say if you are not planning on calling the base class by itself, the then you should define it as an abstract class.

我想说如果你不打算单独调用基类,那么你应该将它定义为抽象类。

#9


0  

The depends on whether you want the base class to be implemented on its own or not.

这取决于您是否希望基类自行实现。

As an abstract class, you can't make objects from it.

作为抽象类,您无法从中创建对象。

#10


0  

Abstract classes are great for predefined functionality, for example - when know the minimum exact behaviour a class should expose but not what data it should use to do it or the exact implementation.

抽象类非常适合预定义的功能,例如 - 当知道类应该暴露的最小确切行为但不知道它应该使用什么数据来执行它或确切的实现。

abstract class ADataAccess
{
    abstract public void Save();
}

Normal (non abstract) classes can be great for similar things but you have to know the implementation specifics to be able to write them.

普通(非抽象)类可以用于类似的事情,但你必须知道能够编写它们的实现细节。

public class DataAccess
{
    public void Save()
    {
        if ( _is_new )
        {
            Insert();
        }
        else if ( _is_modified )
        {
            Update();
        }
    }
}

Also, you could use interfaces (individually or on classes, whether abstract or not) to define the same sort of prototype definition.

此外,您可以使用接口(单独或在类上,无论是否抽象)来定义相同类型的原型定义。

interface ISaveable
{
    void Save();
    void Insert();
    void Update();
}

class UserAccount : ISavable
{
    void ISavable.Save() { ... }
    void ISavable.Insert() { ... }
    void ISavable.Update() { ... }
}

Yet another option may be using generics

另一种选择可能是使用泛型

class GenDataAccess<T>
{
    public void Save()
    {
        ...
    }
}

All these methods can be used to define a certain prototype for classes to work with. Ways to make sure that code A can talk to code B. And of course you can mix and match all of the above to your liking. There is no definite right way but I like defining interfaces and abstract classes, then referring to the interfaces. That way eliminates some of the thought requirements for "plumbing" in higher level classes while keeping the maximum flexibility. (having interfaces takes away the requirement of using the abstract base class, but leaves it as an option).

所有这些方法都可用于为要使用的类定义某个原型。确保代码A可以与代码B通信的方法。当然,您可以根据自己的喜好混合和匹配以上所有内容。没有明确的正确方法,但我喜欢定义接口和抽象类,然后引用接口。这样就消除了更高级别的“管道”的一些思想要求,同时保持了最大的灵活性。 (让接口消除了使用抽象基类的要求,但将其留作选项)。

#11


-7  

I think a lot of you should resit basic OO classes again.

我想很多人应该再次重新启用基本的OO课程。

The basic underlying principle in OOA/OOD is to abstract abstract abstract, until you can't abstract no more. If what your looking at is an abstraction then so be it, thats what your OOA/OOD already told you. However if you sitting there wondering whether "code" should be abstract or not then you obviously don't know what the term means and should go learn basic OOA/OOD/OOP again :-)

OOA / OOD的基本原理是抽象抽象抽象,直到你不能抽象为止。如果你所看到的是一个抽象,那就这样吧,那就是你的OOA / OOD告诉你的。但是,如果你坐在那里想知道“代码”是否应该是抽象的,那么你显然不知道该术语的含义,应该再次学习基本的OOA / OOD / OOP :-)

More to the point you should learn Design Patterns and Harmonic Theory, this will help with your OO designs immensely!

更重要的是,您应该学习设计模式和谐波理论,这将极大地帮助您的OO设计!