今天讲的内容很重要哦,是关于类的继承,这将会是学习java的关键;
继承:是面向对象编程的三大特征之一,也是实现软件复用的重要手段;java的继承具有单继承的特点,即每个子类只能有一个直接父类;
类的继承提高了程序代码的重用性和可扩充性,缩短了软件开发的周期。
实现继承的类成为子类,被继承的类叫做父类;子类和父类的关系,是一般和特殊的关系;
子类继承父类的语法格式是:: 修饰符 class 子类名 extends 父类名{//子类代码 }
extends是继承的关键字,是扩展的意思,,
java的子类不能直接调用父类的构造方法。
编写程序示范子类继承父类的特点。
public class Animal{
public double weight;
public void eat(){
System.out.println("动物在吃东西");
}
}
public class Dog extends Animal{ //继承
public void say(){
System.out.pringln(“狗叫:汪汪汪”);
}
public static void main(String[] args) {
Dog d= new Dog();//new一个对象,对方法进行调用;
d.weight = 150;//继承父类里的公共的成员变量;用对象调用;
d.eat();//继承并调用父类的方法,
d.say();//本类方法的调用;
}
}
子类扩展父类--总是以父类为基础,额外增加新的属性和方法。但有一种情况例外:子类需要重写父类的方法。
子类重写父类的方法
public class Bird{
public void fly(){
System.out.println("我在飞");
}
}
public class Ostrich extends Bird{
//重写Bird类的fly方法----方法覆盖(override)
public void fly(){
System.out.println("我只能在地上奔跑");
}
public static void main(String[] args){
Ostrich os = new Ostrich();
os.fly(); //调用的是Bird的fly还是Ostrich的fly?,方法重复!!
}
}
方法重写时要遵循的规则:
“三同一小一大”规则
“三同”即方法名相同,形参列表相同、返回值类型相同;
“一小”子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
“一大”指的子类方法的访问权限应比父类方法更大或相等;
覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法。
方法重写和方法重载的区别
覆盖是子类和父类之间的关系;而重载是同一类内部多个方法之间的关系。
覆盖一般是两个方法间的,而重载可能有多个重载的方法。
覆盖的方法有相同的方法名和形参表;而重载的方法只能有相同的方法名,不能有相同的形参表。
覆盖时根据调用它的对象来区分方法;而重载是根据形参表来决定调用的是哪个方法。
父类实例的super引用:
如果需要在子类方法中调用父类被覆盖的实例方法,可以用super作为调用者来调用父类被覆盖的实例方法。
如上例中大的重写,只需在子类Ostrich中写一个方法足以;
public void callOverridedMethod(){
super.fly(); //调用父类方法输出“我在飞”
}
super是Java提供的一个关键字,它是直接父类对象的默认引用。
正如this不能出现在static修饰的方法中一样,super也不能出现在static的方法中
如果子类定义了和父类同名的属性,也会发生子类属性覆盖父类属性的情形。
子类的方法直接访问该属性时,都会访问到覆盖属性,无法访问父类被覆盖的属性---通过super来访问父类被覆盖的属性;
刚才我跳到了子类不能直接调用父类的构造函数;现在我们来学学怎么调用父类的构造函数;
调用父类构造方法:子类不会继承父类的构造方法,但有的时候子类构造方法里需要调用父类构造方法的初始化代码。
class Base{
protected double size;//定义一个保护类型的双精度的成员变量;
public Base(){
size=0; System.out.println(“Base类无参构造”);//输出语句,看是否被调用
}
public Base(double s){
size=s;System.out.println(“Base类有参构造”);//同上
}
}
public class Sub extends Base{
private String color;//定义私有成员变量
public Sub(){
color=“blue”;System.out.println(“Sub类无参构造”);
}
public Sub(String c){
color=c;System.out.println(“Sub类有参构造”);
}
public static void main(String[] args){
Sub s1=new Sub();//调用不带参构造函数;
Sub s2=new Sub(“red”);调用带参构造函数;
}
当通过子类构造方法创建子类对象时,默认的先执行父类不含参数的构造方法,再执行子类类构造方法。
要在子类中显式调用直接父类带参数的构造方法,可通过super()调用来实现。
例如,
public Sub(double s,String c){
super(s); //调用Base类中带一个参数的构造方法
color=c;
System.out.println(“Sub类有参构造”);
}
super调用和this调用很像,区别在于super调用的是其父类的构造方法,而this调用的是同一个类中重载的构造方法。
因此,使用super调用父类构造也必须出现在子类构造执行体的第一行,所以this调用和super调用不会同时出现。
子类构造方法调用父类构造方法分如下几种情况:
子类构造方法执行体的第一行代码使用super显示调用父类构造方法,系统将根据super调用里传入的实参列表调用父类对应的构造方法。
子类构造方法执行体的第一行代码使用this显示调用本类中重载的构造方法,系统将根据this调用里传入的实参列表调用本类另一个构造方法。
执行本类中另一个构造方法时即会调用父类的构造方法。
子类构造方法执行体中既没有super调用,也没有this调用,系统将会在执行子类构造方法之前,隐式调用父类无参数的构造方法。
例如:
public class A{
A(){ System.out.println("A"); }
A(int i){ this(); System.out.println("AA"); }
}
class B extends A{
B(){ super(); System.out.println("B"); }
B(int i){ super(i); System.out.println("BB"); }
public static void main(String[] args){
B b=new B(1);//A a =new A(); B b=new B();
}
}
//输出A;直接调用A类的不带参的构造函数;
//当改为B b = new B();输出 A B;先找到B类的不带参的构造函数,而发现在调用B类时必须先返回到父类调用不带参的构造函数;
//当改为B b = new B(1);输出 A AA BB;先找到B类带参的构造函数,发现B类带参函数里调用A类带参构造函数,则返回到A类带参构造函数,发现A类带参构造函数里调用本类不带参构造函数;
//到A类不带参构造函数,然后按顺序最后输出;
就到这里吧,明天继续!!!