什么是继承?
继承是由已有的类创建一个新的类,这个类能够拥有已有类的属性与方法,并且可以根据需求拓展自己的属性与方法。被继承的类称为父类,已有类称为子类。在JAVA中,不支持多继承,也就是说一个子类只能有一个父类,但支持层次继承,一个子类可以有一个父类,也可以有一个新的子类(在家庭中,儿子爸爸爷爷就像是一种层次继承的关系)。
在JAVA中实现继承需要使用关键词extends,例如:
class 子类名称 extends 父类名称{
....
}
class Apple extends Fruit{
....
}
需要注意的是当你编写一个类的时候,没有extends关键字时,它默认继承Object类。
继承的好处
在实际需求中,为什么需要继承类呢。比如,苹果和香蕉都是水果,他们在类别上属于水果,但他们又有不同的地方,颜色,口感都有各自的特性,在这个时候,假如我们分别编写了苹果类和香蕉类,你会发现其实这两个类里面会有代码重复之处,这还只是数量少的情况,不会感到编写重复代码的烦恼,如果是在数量多的情况下,比如所有水果都去写一个类,就会比较繁琐,何不先归结出他们的共同点,在共同点完成后,在写一个新的类描述各自的属性不是更高效?
由上述例子可以知道继承有如下优点:
代码更加简单高效,重复度低,可以直接使用父类的属性与方法
子类扩展性更好,拥有自己的属性与方法
子类的继承性
在JAVA中有四种访问权限分别是private,public,protected,缺省:
public class Fruit {
private String name;
public String getName() {
return name;
}
protected void setName(String name) {
this.name = name;
}
void show(){
System.out.println(name+"的颜色为:"+color);
}
}
四种访问权限的属性与变量其实都会继承给子类,但因为权限问题,一些属性和方法在子类中也无法使用。
同包继承性
如果父类与子类都在同一个包下,除private权限的属性和方法不能使用外,其他权限都可以直接使用,并且权限不变。
跨包继承性
如果子类父类不在同一个包下,除private和缺省权限的属性和方法不能使用外,其他权限都可以直接使用,并且权限不变。
成员变量隐藏和方法重写与方法重载
继承也并不意味着全盘照搬,也可以改写已有的方法或属性。
成员变量隐藏
子子类中可以声明一个与父类同名的变量,这样在子类创建对象调用的时候就会调用子类的变量而不是父类的变量,从而实现对父类成员变量的隐藏。
方法重写
在很多时候我们往往不需要父类中的一些方法,可能它实现的结果和我们想要的不一样,这时候我们就可以实现方法重写或者叫方法覆盖。方法名和参数个数类型和父类方法完全相同。例如:
class A {
double getPrice(double x,double y){
return x+y;
}
}
class B extends A{
double getPrice(double x,double y){
return x*y;
}
}
public class Test {
public static void main(String[] args) {
B b=new B();
double i=b.getPrice(3,4);
System.out.println("结果为:"+i);
}
}
![](https://img-blog.csdnimg.cn/img_convert/d8b49dffec12f350962c7588dd3b75e9.png)
方法重载
为了区别方法重写,还要介绍一下方法重载。方法重载是方法名相同,方法参数的个数、顺序或者类型不同的方法。例如:
public interface Action {
public void eat();
public void pick();
public void store();
}
public class Apple implements Action{
public void eat() {
System.out.println("苹果真好吃啊");
}
public void pick() {
System.out.println("苹果真红啊");
}
public void store() {
System.out.println("苹果真实惠啊");
}
}
public class Pineapple implements Action {
public void eat() {
System.out.println("菠萝真好吃");
}
public void pick() {
System.out.println("菠萝真红啊");
}
public void store() {
System.out.println("菠萝真实惠啊");
}
}
![](https://img-blog.csdnimg.cn/img_convert/8fd0443c8d78498ecddf93068856535c.png)
Super关键字和This关键字
子类构造对象的过程
子类在创建对象的时候,首先会调用父类的构造对象,才会调用子类自己的构造对象,如果父类没有声明构造函数那就是一个无参的构造函数。在不了解这个过程的时候,往往会出现这样的错误。这就是父类有参的构造函数需要传入参数否则就会报错。
![](https://img-blog.csdnimg.cn/img_convert/0080cb8a525f44ac8791f224e955725f.png)
![](https://img-blog.csdnimg.cn/img_convert/5d24ad6d4e11101f89b5c6a04c90b180.png)
This关键字
当你遇到上述问题的时候,你需要给有参构造函数传值,你或许会想到在声明对象的时候传值,但也可以使用this关键字,在无参的构造函数中传递给有参的构造函数。
public class Fruit {
String name;
String color;
public Fruit() {
this("桃子", "粉红色");
}
public Fruit(String name, String color) {
this.name = name;
this.color = color;
}
}
public class Test {
public static void main(String[] args) {
//利用this关键字实现对有参函数传值
Fruit pe=new Fruit();
System.out.println(pe.getName()+" "+pe.getColor());
//构造对象时直接传值
Fruit pe1=new Fruit("梨子","绿色");
System.out.println(pe1.getName()+" "+pe1.getColor());
}
}
Super关键字
解决上述方法除了可以使用this,也可以使用Super方法实现对父类的构造函数传递值。这样程序也不会报错。
public class Apple extends Fruit{
public Apple() {
super("桃子","粉红色");
}
}
这两类关键字,不仅可以用作构造函数,更可以用来实现对同名函数的覆盖与重写。
自动转型与强制转型
自动转型又称向上转型。苹果和香蕉都是水果,水果类就是苹果和香蕉的父类,但如果说苹果是水果,苹果也就失去了特有的属性和行为,水果这个类就是苹果的上转型对象。
Fruit fur=new Apple();
或者
Fruit fur;
Apple apple=new apple();
fur=apple;
上转型对象具有如下特点:
(1)上转型对象不能使用子类新增的成员变量和方法,父类能调用除了子类中独有的方法外的方法。
(2)上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法和重写的方法。因此,当上转型对象调用重名方法时,一定是子类的重写方法。
public class Apple extends Fruit{
public void eat(){
System.out.println("苹果真好吃");
}
}
public class Fruit {
public void eat(){
System.out.println("水果真好吃!");
}
}
public class Test {
public static void main(String[] args) {
Fruit apple=new Apple();
apple.eat();
}
}
![](https://img-blog.csdnimg.cn/img_convert/b69cc4d1b67ab32930d10e0ba16bd6a3.png)
不可以这样写:这种错误也可以理解,往往是上转,也就是大到小,因为大拥有小的所有属性,而小的却拥有独特的属性和行为,比如苹果是红的,水果却不一定都是红色的。
![](https://img-blog.csdnimg.cn/img_convert/ac13dfff9c1a472a3d902aa3876fea99.png)
自动转型在java中也有很多体现,在GUI编程中,想要获取一个控件的属性,他往往不会返回一个精确的控件类型,比如我要获得一个按钮,但他返回的是一个Object类,为什么呢,因为系统并不知道你获取的组件类型,为了不出错,它只能返回一个大类,这个大类是包括各种组件的,你想用什么组件,就进行强制转型。
e.getSource()==Object
JButton jbu = (JButton)e.getSource();