黑马程序员---------Java基础知识:继承
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
第一篇博客内说到了类继承,这一篇就说说继承的问题。
一:什么是继承?
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独的那个类即可。
二:继承中的子父关系
继承的关系当中有子类和父类,被继承的类成为父类或者超类,继承父类的类称为子类。每个父类的子类可以有多个,但是每个子类只能有一个父类,就好比一个父亲可以有多个亲生孩子,但是每个孩子只能有一个亲生父亲一样。
子类和父类的关系,子类可以字节访问父类的非私有属性和行为。通过extends关键字实现类与类之间的继承关系。
三:继承的注意事项:
继承不能为了获取某个类里面的某个功能而去继承,类与类之间要有从属关系。比如动物是父类,人为子类。即人是动物的一种。
子类只能继承一个父类,而父类可以有多个子类,这个称为单继承。单继承的好处在于,如果一个类继承了多个父类,而父类当中有多个相同名字的函数,在调用时就会出现不知道调用哪个类的函数的情况。
Java支持多层继承,即一个子类的父类可以还有父类,一个子类的子类还可以有子类。
如
class fu
{
}
class zi extends fu//子类继承了父类,fu类为父类
{
}
继承实例:
class Person//一个人类
{
String name;//有名字和年龄
int age;
}
class Student extends Person//学生是人的一个类
{
Student()//构造函数,打印出"good study",字符串
{
System.out.println("good study");
}
}
class Worker extends Person //工人继承人类
{
Worker()
{
System.out.println("good work");
}
}
public class ExendsDemo {
public static void main(String[] args) {//主函数
//创建对象,打印出good study因为构造函数在对象的创建时就存在并运行
Student s = new Student();//
s.name = "zhagnsan";//将名字传入
System.out.println(s.name);//打印出对象的名字
Worker w=new Worker();
System.out.println(w.name);
w.name = "lisi";
System.out.println(w.name);
//System.out.println("good work");
}
}
运行结果是:
good study
zhagnsan
good work
null
lisi
四:继承的好处:
提高了代码的复用性。当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类的方法,这样就可以由父类的功能又可以有自己特有的功能。
让类与类之间产生了关系,提供了多态的前提。
继承里面的几个关键字:
Super:代表的是父类引用,当子父类出现同名成员时,可以用super进行区分,如super.show();this.show(); 子类要调用父类的构造函数是可以使用super语句,super();
This:代表本类的引用。
final: 最终的意思。
继承的一个弊端:打破了封装性。但不可否认,继承的出现提高了类的复用性。对于一些类,或者类中功能,是需要被继承,或者复写的。所以有了final:。
final特点:
1. 这个关键字是一个修饰符,可以修饰类,方法,变量。
2. 被final修饰的类时一个最终类,不能被继承
3. 被final修饰的方法时一个最终方法,不能被覆盖。
4. 被final修饰的变量是一个常量,只能被赋值一次,这个常量名字母全大写表示。
刚刚写到的继承提到了重写的问题,还有一个问题是重载,重载和重写是不一样的。
区别是:
重载:发生于一个类中,重载的两个函数名必须一样,参数个数或者参数类型不一样。
重写:发生在子类和父类当中,子类和父类的函数名一样,参数列表也一样。但是子类的方法的权限必须大于父类,而且抛出的异常和返回值只能比父类小。
五:继承后各个成员的变化
1.变量。
当子父类中定义了相同的名称的成员变量,
子类要使用父类中的同名变量时,需要使用关键字super来区分。
一般不会出现这种情况,因为父类中有了,子类不需要定义。
而且父类定义时,一般变量都私有化。
2.函数。
子类可以直接访问父类中非私有的成员函数。
特殊情况:当子类中定义了与父类一模一样的方法时,会发生覆盖操作。大多指的是非静态方法。最终会运行子类的方法,父类相当于被覆盖了。因而出现了函数的另一个特性:覆盖(重写,复写)。
什么时候用覆盖呢:
当父类的功能要被修改时,不建议修改源码。因为是灾难。只要通过一个类继承原有类,定义一个新的升级后的功能即可。但是功能是相同的,只是实现方法改变。这是子类可以沿袭父类中的功能定义,并重写功能内容。这就是覆盖。
函数覆盖:
在子类当中出现和父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。其中父类的私有方法时不能被覆盖的。因为是私有,不是为外部提供的方法,因而子类没有权限进行覆盖。
覆盖的注意事项:
1.覆盖时,子类方法的权限一定要大于父类的权限,否则权限不够,无法覆盖。
2.静态只能覆盖静态。原因是静态是随着类的出现而出现比非静态出现早,假如静态去覆盖非静态, 在静态方法出现时,非静态方法还没出现,因而不能覆盖。
3.构造函数。
构造函数可以本类进行对象初始化,也可以给子类对象进行初始化。子类对象初始化过程:子类中的所有构造方法都会访问父类中空参数的构造函数,因为每一个构造函数的第一行,都有一句隐式的super语句。
为什么要有这条super语句?
因为子类会获取到父类中的数据,必须要先明确父类对数据的初始化过程。当父类中没有空参数构造函数时,子类构造函数必须通过super句来明确要访问的父类中指定的构造函数。当时子类构造函数也可以通过this语句访问本类中的构造函数。但是子类中肯定,至少有一个构造函数会访问父类。
六:继承中的涉及的接口,抽象类,多态
1. 抽象类
抽象类就是抽象方法所在的类,该类需要被abstract关键字所修饰。什么是抽象方法呢?类在不断抽取过程中,将共性内容中的方法声明抽取,但是方法不一样,没有抽取,这时抽取到的方法,并不具体,需要被指定关键字abstract所标示,声明为抽象方法。
抽象类的特点:
1. 抽象方法只能被定义在抽象类的那工作,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2. 抽象方法只能定义方法声明,并不定义方法实现。
3. 抽象类不可以被创建对象。
4. 只有通过子类继承抽象类并覆盖抽象类中的所有抽象方法之后,该子类才能被实例化。否则该类还是抽象类。即在继承抽象类后没有把所有抽象方法覆盖,则这个子类还是抽象类。就如从一个人那传染了感冒,传染后没有把感冒病毒杀完,那还是在感冒。病毒的过程就是对抽象方法的覆盖。
抽象类的一些问题
1. 抽象类中是否有构造函数呢?抽象类也有构造函数的,是给子类进行初始化、
2. 抽象类中是否可以定义非抽象方法呢?抽象类中是可以定义非抽象方法的。它只是比一般的类多了抽象方法而已。
3. 抽象类关键字abstract不能和哪些关键字共存?不能和final共存,因为final修饰的类不能被继承,抽象类必须被继承所以不能存在。不能与Private共存是因为Private是私有的,在被继承后无法被调用也无法被覆盖,这跟抽象类存在的作用相反。不能与Static共存,static是静态,类存在则存在,因为抽象类里面没有具体内容所以是不能与static共存。
4. 抽象类中能不能不定义抽象方法?这个是必然可以的。
2. 接口
接口使用关键字interface定义,包含的成员变量最常见的是全局变量和抽象方法。它们有固定的修饰方法。
成员变量的修饰方法:public static final
成员方法的修饰方法:public abstract
示例:
Interface Inter
{
publicstatic final int x=3;
public abstract void show();
}
class A implements Inter
{
public void show(){/*写入需要实现的功能*/}
}
因为接口中有抽象方法所以接口不能实例化。因此接口的子类必须实现接口中所有的抽象方法后才可以实例化。类与类之间存在着继承的关系,而类与接口则存在实现关系。
接口可以被多实现,就是一个类可以实现多个接口,但是只能继承一个类。一个类在继承另一个类的同时可以实现多个接口。而接口与接口之间存在着继承关系,接口可以多继承接口。
接口的特点:
1. 接口是对外提供的规则。子类必须实现它的方法。
2. 接口是功能的扩展。
3. 接口的出现降低了耦合性。
接口与抽象类的共性和差别:
抽象类一般用于描述一个体系但愿,将一组共性内容进行抽取,特点是可以在类的当中定义抽象内容让子类实现,可以定义非抽象内容让子类直接调用。
接口一般用于定义对象的扩展功能,是在继承之外还需要这个对象具备的一些功能。
抽象类和接口的共同点是:都是不断向上抽取的结果,子类都需要复写其方法。
抽象类和接口的不同点:
1. 抽象类只能被继承。接口需要被实现,而且可以实现多个接口。
2. 抽象类中可以定义非抽象方法,子类可以直接继承使用。接口中都是抽象方法,需要子类去实现。
3. 抽象类中成员修饰符可以自定义,而接口中成员修饰是固定的。
3. 多态
多态的好处:提高了程序的扩展性。
多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不能访问子类中特有的方法。
多态的体现:父类引用或接口引用指向自己的子类对象。如Animal a = new Cat();
多态的前提:
1. 必须有继承或实现。
2. 通常会有覆盖操作。
多态出现思想上的变化:以前是创建对象并指挥对象做事情。有了多态以后,我们可以找到对象的共性类型,直接操作共性类型做事情即可,这样可以指挥一批对象做事情,即通过操作父类或接口实现。
多态在子父类中的成员上的体现的特点:
1. 成员变量:在多态中,子父类的成员变量同名。无论编译还是运行,成员变量参考的都是引用成员变量所属的类中的成员变量。即,编译运行,成员变量都 看左边。
2. 成员函数。编译看引用变量所属的类,运行时看对象所属的类。即编译看左边,运行看右边。
3. 静态函数。静态方法时哪个类引用就看哪个类的静态方法,即编译运行都看左边。
总结:成员变量,成员函数,静态函数除了成员函数运行时看右边,其他的编译和运行都看左边。