class Animal {
void eat() {
System.out.println("吃东西");
}
}
class Cat extends Animal {
void shout() {
System.out.println("喵喵...");
}
}
class Dog extends Animal {
void shout() {
System.out.println("汪汪...");
}
}
public class AnimalDemo {
public static void main(String[] args) {
Cat c=new Cat();
c.eat();
c.shout();
Dog d=new Dog();
d.eat();
d.shout();
}
}
以上是一个体现继承关系的程序,
当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可,程序中猫和狗都有吃东西的技能,就可以做个单独类,然后继承就可以实现这个功能。
1)子父类出现后,类成员(变量,函数,构造函数)的特点:
1、变量
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this。子类要访问父类中的同名变量,用super。 super的使用和this的使用几乎一致,且两者都存在于方法区中。 this表示本来对象的引用。 super表示父类对象的引用。
2、函数——覆盖
void eat() {
System.out.println("啃骨头");
}
当在上段程序中的class Dog中加入如上方法,调用eat()方法时,打印结果是:啃骨头。为什么呢?
当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:覆盖。
当子类继承父类,沿袭了父类的功能,到子类中。但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。子类同时具有父类方法中的内容时,可以用super.方法()。
注:1、子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败;2、静态只能覆盖静态;3、父类中的私有方法不能被重写; 4、(区分重载和覆盖)重载:只看同名函数的参数列表。覆盖:子父类方法要一模一样。
3、构造函数 在对子类对象进行初始化时,父类的构造函数也会运行。那是因为子类的每一个构造函数默认第一行有一条隐式的语句super()。当父类中没有空参数的构造函数时,子类必须手动通过supe语句或者this语句形式来指定要访问的构造函数,如:super(参数)指向父类特定构造函数,this()指向本类构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。(注:super语句和this语句一定定义在子类构造函数中的第一行。)
三、final修饰符
继承的出现,打破了对象的封装性,使得子类可以随意复写父类中的功能。这也是继承的一大弊端。那么怎么解决这个问题呢?这里就引出了一个新的关键字——final(最终)。
final作为一个修饰符。具有以下特点:
1、可以修饰类、函数、变量。
2、被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。
3、被final修饰的方法不可以被复写。
4、被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。
5、内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。