Java的继承可以在结构和功能上为程序带来很好的便捷性和灵活性。但是在继承的过程中,如果不能够非常深刻的理解这其中的一些规律规则,就不能够很好的发挥继承带来的优势,甚至会造成一些错误。
继承和abstract
这三个类的代码如下:
import java.awt.event.*;
public abstract class grandfather implements ActionListener
{
public abstract void m1();
}
import java.awt.event.*;
public abstract class father extends grandfather
{
public abstract void m2();
}
import java.awt.event.*;
public class son extends father
{
public void m1()
{}
public void m2()
{}
public void actionPerformed(ActionEvent e)
{}
}
在这个程序中,最原始的基类---grandfather,是一个抽象类,它有一个m1()的抽象方法。此外,grandfather还实现了ActionListener接口,按理说是需要重写接口中的actionPerformed()方法的,但由于grandfather本身是一个抽象类,就可以不覆盖actionPerformed()。(若将grandfather又抽象类改为普通类,编译将无法通过,编译器会提示:grandfather不是抽象的,并且未覆盖XXX中的抽象方法XXX(parameters) )。
按照继承的规则,其子类---father,在继承grandfather之后,需要对m1()进行重写(overriding),但碰巧的是,father自身有一个抽象方法m2(),所以father也必须也声明为一个抽象类(否则无法通过编译),这个时候,由于father是抽象类,就可以不去覆盖其基类的抽象方法了。
最后一个类,father的子类---son,是一个普通的非抽象的类,这时候,由于son不抽象,就无法逃过重写的责任了,它必须将其基类father的抽象方法m2()进行重写,不仅如此,由于其基类father未重写最原始基类grandfather的抽象方法m1()和actionPerformed(),son还需要重写这两个方法。否则会编译器无法通过编译。
也就是说,一个抽象方法最终一定会得到重写,就算第一个子类将自身定义为抽象类,逃掉了重写的责任,以后也必然会有一个非抽象的子类来完成早该完成的重写任务。当然,如果所有类都是抽象的,抽象方法就可以一直不去重写,不过这显然是不可能,也是没有意义的。
在这个程序中,我认为每个类都应该定义好自己的行为,及时的重写自己该重写的方法,这样,既可以避免许多编译无法通过的麻烦,也可以提高类的内聚性,使一个类的更加凸显出自己的作用与功能(比如说grandfather实现ActionListener的接口,肯定是需要对component进行监听,那么actionPerformed()方法理应在grandf里就实现,而不该拖到son类中实现),同时还必然为子类减轻了负担。
更加合理的代码如下:
import java.awt.event.*;
public abstract class grandfather implements ActionListener
{
public abstract void m1();
public void actionPerformed(ActionEvent e)
{}
}
import java.awt.event.*;
public abstract class father extends grandfather
{
public abstract void m2();
public void m1(){};
//public void actionPerformed(ActionEvent e)
//{}
}
import java.awt.event.*;
public class son extends father
{
public void m2()
{}
//public void m1()
//{}
//public void actionPerformed(ActionEvent e)
//{}
}
此时father和son中的被注释掉的代码,视具体情况选择需不需要,father中的m1()和son中的m1(),m2(),和actionPerformed()就不仅仅为通过编译了,而是为了通过overriding与inheritance为类自身提高性能和功能,从而提高程序的效率。
分享到:
相关推荐
继承表达了“is-a”关系,即子类是父类的一种特殊类型。然而,过度依赖继承会导致一系列问题: 1. **继承层次过深**:当继承链变得很长时,理解一个类的行为需要查看整个继承树,这对代码的阅读和理解造成困难。 2....
在Python编程语言中,继承是面向对象编程的一个核心特性,它允许子类(派生类)从父类(基类)那里获得属性和方法,从而实现代码的复用和扩展。这里我们将深入探讨单继承、多继承以及多层继承的概念、语法以及相关...
继承是类之间的一种关系,子类继承自父类,从而获取了父类的部分特性。这种关系模拟了现实世界中的遗传关系,使得子类可以重用和扩展父类的属性和方法。Java中的继承是单继承的,也就是说一个子类只能有一个直接父类...
#### 一、什么是继承? 在面向对象编程中,继承是一种机制,允许程序员定义一个类(称为子类或派生类)来继承另一个类(称为父类或基类)的属性和方法。通过继承,子类不仅可以重用父类的功能,还可以根据需要添加...
**方法的重写(Overriding)** 是指子类继承父类后,可以重新定义父类的方法。子类重写父类的方法时,必须遵循以下规则: 1. 方法名、参数列表和返回类型必须完全一致。 2. 子类方法的访问级别不能小于父类方法的...
- 子类继承父类时,默认只能继承公有(`public`)和受保护(`protected`)的成员,而不能继承私有(`private`)成员。因此,正确答案是 **C. 子类可以继承父类的公有的属性和方法**。 8. **继承声明** - **题目**: 现有...
当一个类B继承自另一个类A,B称为子类,A称为父类。子类B不仅可以继承父类A的所有公有(public)和受保护(protected)成员,还可以有自己的特有成员。当我们声明一个父类类型的引用并将其赋值为子类的对象时,如`...
1. 子类继承了父类的所有非私有属性和方法,但不能继承带有`private`修饰符的属性和方法,因为`private`是类内可见。 2. 构造函数不能被继承,但子类可以通过`super()`关键字调用父类的构造器来初始化父类的部分。 3...
有关子类和父类。A是子类,Teacher是父类。A是Teacher 的一种(子类)会继承父类李非私
在继承关系中,子类继承了超类的所有成员变量和成员方法,但是子类可以对超类的成员变量和成员方法进行覆盖或重写。 Java继承的特点: 1. 单继承:Java只支持单继承,即一个类只能继承一个超类。 2. 多层继承:...
在C++编程语言中,多重继承是一个特性,允许一个类(子类)继承自多个基类(父类)。这种设计模式使得子类可以同时获得多个基类的特性,增加了代码的复用性。然而,多重继承也带来了一些复杂性和潜在的问题,其中最...
Java的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如A类继承B类,B类继承C类,所以按照关系就是C类是B类的父类,B类是A类的父类,这是java继承区别于C++继承的一个特性...
继承是一种“is-a”关系,允许一个类(子类)继承另一个类(父类)的属性和方法。在支持多继承的语言中,一个类可以同时继承多个父类,这样可以获得多个父类的特性。然而,Java选择了单继承,即一个类只能有一个父类...
在面向对象编程语言中,子类继承自父类时会自动拥有父类的所有非私有成员(包括属性和方法)。这意味着子类可以被视为是父类的一种特殊形式,即“子类是一种特殊的父类”。因此,可以通过父类的引用变量来操作子类...
在面向对象编程语言中,继承是一种非常重要的概念,它允许我们定义一个类(称为子类或派生类)来继承另一个类(称为父类或基类)的特性和行为。通过继承,可以有效地复用代码、扩展功能并构建出更为复杂的类结构。本...
继承是特殊的is-a关系,即子类继承父类,说明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法。子类和父类之间存在着继承关系,子类继承父类的所有属性和方法。 二、继承的语法格式 Java继承的关键字...
面向对象三大特征之继承 ... 如果父类装起来,子类无法直接访问,但是子类确实有继承下来, 可以通过父类提供公共方式进行访问 如果子类编写了有参构造,父类是封装状态,那么有参构造使用s
例如,在单继承中,子类的成员变量和基类的成员变量会被合并到一起。在多重继承中,每个基类的成员变量都会被复制一份。在虚继承中,虚基类的成员变量会被所有派生类共享。 在成员变量和成员函数的访问方面,C++...