java的基本单位是类,而类与类之间又存在着什么联系呢?通过这节课我们对于类有了更为深刻的了解。类和类之间可以存在继承关系。由一个类派生出来的另一个类称为子类(也可以叫超类,或者派生类),将派生出子类的类称为父类(或者说基类)。继承的好处:提高代码的重用性;提高程序的扩展性。
类的继承的关键字是:extends,格式为:public class 类名b(子类)extends 类名a(父类){ }
注意:java中只存在单继承关系,每一个类都是至多只能有一个父类
既然子类和父类之间存在着继承关系,那么子类到底继承到了父类的那些属性和方法呢?答案是全部,子类继承了父类的全部属性和方法。值得注意的是:子类继承的方法和属性和子类能调用的父类属性和方法是不一样的。这是容易被我们所忽略的事,我们很容易将继承的方法和属性与可以调用的方法和属性弄混淆。
类中的访问修饰符有四种:private、默认的、protected、public。这四种访问修饰符的作用区域不同,局限性由高到低。
关于存在继承关系的类中能调用的属性和方法有不同的情况:
1.子类和父类同一个包下:默认的,protected,public属性和方法能被子类的对象以及在子类中调用。
2.子类和父类不在同一个包下时:
1)创建的对象不在子类或者父类中时(即在第三方类),可调用的属性和方法就只有public。
2)如果在子类的{}中,可调用的属性和方法有public和protected的。
类中方法的重写:
我们生活中方法的重写也很常见:司机都有开车这个方法,司机作为父类,公交车司机作为子类,两个司机类在开车这个方法里实现的路径不一样,但是它们的参数类型个数顺序等等是一样的。
要实现方法代码重写的条件有三个:
(1)是必须存在继承关系;
(2)是方法的返回值数据类型,方法名,参数类型,参数名,参数个数,参数顺序必须完全一致。
(3)是子类在重写方法时,访问修饰符的范围可以大于或者等于父类方法的访问修饰符。
当实现方法重写后,如果你创建的对象是子类的对象,那么会优先调用子类的方法,如果子类没有该方法,才会执行父类中定义的方法。
自动转型:要有自动转型也必须要有继承关系,其格式为:1)、父类 对象名;
对象名 = new 子类名(实参,...);2)、父类 对象名 = new 子类名(实参,...);
自动转型的缺点:调用子类中有而父类中没有的方法则会报错,主要是由于Java的编译机制引起的问题,Java在编译的时候只会根据对象名的类型进行编译,而不会去看new后面的内容,根据对象名的类型去查找是否存在该方法,如果存在,则通过编译,如果不存在则报错。
其优点:实现多态,减少重复的代码。所谓多态就是由方法重载,继承,方法重写,自动转型等技术点的组合。
关于自动转型的实例:克里斯有很多种类型的笔,克里斯要写字,可以用铅笔也可以用毛笔,也可以用钢笔……
练习:
package 自动转型;
//创建一个Pen类
public class Pen {
//程序入口
public String name;//设置姓名属性
//定义设置姓名属性的方法
public void setName(String name){
this.name = name;//将传入的参数值赋给调用该构造方法的对象姓名属性
}
//定义获取姓名属性的方法
public String getName(){
return name;//返回姓名属性
}
}
package 自动转型;
/**
* 定义一个子类Pencil
**/
public class Pencil extends Pen{
//定义一个带参构造方法
public Pencil (String name){
//将传入的参数值赋给调用该构造方法的对象姓名属性
this.name = name;
}
}
package 自动转型;
/**
* 定义一个Brushpen类
**/
public class Brushpen extends Pen{
//定义一个带参构造方法
public Brushpen (String name){
//将传入的参数值赋给调用该构造方法的对象姓名属性
this.name = name;
}
}
package 自动转型;
/**
*定义一个User类
*/
public class User {
protected String name;//设置姓名属性
//定义一个带参的构造函数
public User(String name){
this.name = name;//将传入的参数值赋给调用该构造方法的对象姓名属性
}
//设置一个获取姓名属性的方法
public String getName(){
return name;
}
//定义一个写字的方法,使用自动转型来接受参数
public void write(Pen pen){
System.out.println(this.getName()+"正在用: "+pen.getName()+"写字");
}
}
package 自动转型;
/**
* 定义一个Main类
*/
public class Main {
/**
* 程序的主函数入口
*/
public static void main(String[] args) {
//创建一个Pen类对象
Pen pen = new Pen();
//用实例化以后得到的pen对象去调用Pen类中设置姓名属性的方法
pen.setName("笔");
//创建一个Pencil类对象
Pencil pencil = new Pencil("铅笔");
//创建一个Brushpen对象
Brushpen brush = new Brushpen("毛笔");
//创建一个User对象
User user = new User("克里斯");
//调用write方法
user.write(pen);
user.write(pencil);
user.write(brush);
}
}