Java 在什么情况下我需要扩展类?

Java 在什么情况下我需要扩展类?,java,class,extend,Java,Class,Extend,我正在学习java,我想知道在什么情况下,您会希望像下面这样扩展一个类: 谢谢 几乎从来没有。最好只扩展为其积极设计的类。大多数类实现者没有考虑到如果人们扩展他们的类会发生什么。有各种各样的问题 作文是你最好的朋友 漏洞包括 您无法在子类中正确实现equals()或hashCode() 您违反了封装,现在依赖于另一个类的内部 您容易受到父类更改的影响 您需要接受添加到父类的任何新方法 您必须担心Liskov替换原则,这可能会导致微妙的错误 Josh Bloch在他的优秀著作《有效Java,

我正在学习java,我想知道在什么情况下,您会希望像下面这样扩展一个类:


谢谢

几乎从来没有。最好只扩展为其积极设计的类。大多数类实现者没有考虑到如果人们扩展他们的类会发生什么。有各种各样的问题

作文是你最好的朋友

漏洞包括

  • 您无法在子类中正确实现equals()或hashCode()
  • 您违反了封装,现在依赖于另一个类的内部
  • 您容易受到父类更改的影响
  • 您需要接受添加到父类的任何新方法
  • 您必须担心Liskov替换原则,这可能会导致微妙的错误

Josh Bloch在他的优秀著作《有效Java,第二版》中,在几个地方谈到了这一点,包括第8、16和17项

当您想要创建一个通常与超级类(被扩展的类)相似的类时,可以对其进行扩展和自定义。覆盖它的一些函数和/或添加函数。

这是一个“is-a”场景,是OOP的三大支柱之一(继承、封装、多态)。如果您有一个类“动物”,那么您可能希望从“动物”扩展“狗”类。狗是一种动物,但反过来不是。所有的动物都有细胞,但狗除此之外还有其他特征。这是一个非常基本的概念。

扩展类是OOP的基础之一,还有接口。比如说,你们有一个叫做Building的普通类。它的成员包括建筑所在的区域、城市(或坐标)等


现在,使用extend,您可以将房子指定为“小屋”、“摩天大楼”等。它们将具有父级+其他功能(例如SkyScaraper的层数)

继承有三个主要缺点。即使关系是“是”的关系,在决定继承类时考虑这三个。

  • 部分继承是不可能的。您不能部分扩展
  • 它是静态链接的。继承关系是静态的。您无法在运行时更改该关系
  • 不能通过继承来限制行为。(C++中可能通过私有继承而不是java)

  • 扩展类时,原始类和新的扩展类之间存在父子关系

    扩展父类的子类将拥有父类的每个成员,而无需再次声明它们。即使是私人成员,您也无法直接访问他们

    当您希望新类具有与原始类相同的所有功能以及其他功能时,可以扩展类。然后,子类可以添加新功能,或者重写父类的某些功能

    当您想要拥有一组相关的、共享一些公共功能的类时,您也可以使用扩展,但在细节方面有不同的实现。例如,通常对于图形界面,您有一个
    控件
    类,该类具有与渲染和定位相关的功能。然后,它的子项被称为
    按钮
    文本框
    组合
    等。这些子项都有一些共同的实现,但每个子项的细节都不同


    还要确保学习接口。有时,您需要很多相关的类,以便它们有一组通用的成员,但没有共享的功能。在这种情况下,实现接口可能比扩展公共类更好。接口就像一个类,但没有实现(它只是告诉您它的实现者应该拥有哪些成员)。

    一般来说,扩展类是为了让您基于某种东西创建类。例如,为了创建活动,必须扩展活动。如果类要设置IntentService,则必须扩展类以使用IntentService

    public class AClassNameHere extends Activity  implements OnClickListener {
    
    public class ClassName extends IntentService{
    

    您可以扩展超类以覆盖超类方法,使其特定于子类 例如:

    如果您的超类是具有泛型行为的泛型类,例如Animal类可以是一个泛型类,如

    class Animal{
    private String name;
    public String getVoice(){
    return "Animal";
    }
    
    }

    现在,您需要创建一个类Cat,它是类型为Animal,但具有不同的声音,然后您只需扩展超类Animal并重写getVoice()方法 像

    现在如果您有这样的代码: 动物猫=新猫(); cat.getVoice()//它将返回“喵”

    实际上,您可以在许多情况下使用此选项,如 1.将现有框架类扩展到自定义类。 2.如果您正在开发任何框架,您可以公开一些您希望用户自定义的类


    但压倒一切的是一种关系

    面向对象的良好实践是
    向接口编程
    。但在某些情况下,您可以利用继承:例如,当您的顶级类有一个定义良好的行为(我指的是具体的代码),所有子类都将继承该行为时,这将减少代码、复杂性,并为您提供更好的维护场景

    另一方面,如果您的模型太抽象(基本行为不是很清楚),那么您应该考虑使用接口


    如果您正在创建真实的软件,不要忘记设计模式——可能有人已经解决了您的问题。

    使用继承的主要原因是扩展基类的行为

    例如,如果你正在制作一个视频游戏,你可能会有一个
    Character
    类,它包含了一个角色在世界上导航和做任何其他事情所需的所有代码

    然后可以使用
    Player
    NPC
    扩展
    Character
    ,以便<
    class Cat extends Animal{
    
    public String getVoice(){
    return "mew";
    }   
    }
    
    protected void MoveToLocation(x, y)
    {
     //movement logic goes here
    }
    
    public void mouseClicked (MouseEvent mouseEvent)
    {
        MoveToLocation(mouseEvent.getX(), mouseEvent.getY());
    }
    
    protected void decideWhereToGo()
    {
        int destinationX, destinationY;
        //logic for determining destination
        MoveToLocation(destinationX, destinationY);
    }
    
    public class Vehicle
    {
      void engine()
    }
    
    protected class Car extends Vehicle
    {
     void tyres()
    }
    
    protected class Boat extends Vehicle
    {
     void propeller()
    }