1、概念:把多个类中相同的属性和行为进行向上抽取得到另一个类,之后定义这些类的时候就不再用定义这些相同的属性和行为,只要让这些类继承抽取出来的类即可。这样一来,这具有相同属性和行为的类称为子类,抽取出来的是父类,两者之间的关系叫做继承。例如:要定义一个描述猫的类,首先定义一个动物类,让后让猫类继承动物类,所以猫的描述类就是子类,动物类就是父类。Java中的继承用extends来表示,格式为——class 子类 extends 父类。
2、特点:
1)提高了代码的复用性。
2)让类与类之间产生了关系,有了继承关系,才有了多态的特性。
3)java 语言中java 只支持单继承,不支持多继承(因为多继承容易带来安全隐患)。
4)java 支持多层继承,也就是一个继承体系。
5)父类的私有成员不能被子类继承;父类的构造方法不能被继承(也就是子类可以继承父类中非私有成员)。
继承关系出现之后,因为父类中定义的是子类所共有的东西,所以要使用继承体系中的一个功能,就要查阅父类功能,创建子类对象使用功能。而继承体系中的子父类的成员也具有一定的特点,可以从类中的变量、函数、构造函数分析。
3、变量
如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用 this;子类要访问父类中的同名变量,用 super。
1)super 的使用和 this 的使用几乎一致,this 代表的是本类对象的引用,super 代表的是父类存储空间。
2)在子类方法中使用一个变量时:(就近原则)首先,在方法的局部变量中找这个变量,有则使用。否则,在本类中找成员变量,有则使用。否则,在父类中找成员变量,有则使用,否则,报错。
4、函数
1)当子类出现和父类一模一样的函数时,若子类对象调用该函数,会运行子类函数,如同父类的函数被覆盖(重写)一样。
2)当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。
Note:
用子类对象使用一个方法时。首先,在子类中找这个方法,有则使用。否则,在父类中找这个方法,有则使用。否则,报错。
5、构造函数
1)在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句 super();
2)super();会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是 super();
Note:
子类的所有构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super();当父类中没有空参数的构造函数时,子类必须手动通过supe语句或者this语句形式来指定要访问的构造函数。当然子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
6、final关键字
继承的出现,打破了对象的封装性,使得子类可以随意复写父类中的功能。这也是继承的一大弊端。那么怎么解决这个问题呢?这里就引出了一个新的关键字——final(最终)。
final作为一个修饰符。具有以下特点:
1)可以修饰类、函数、变量。
2)被final修饰的类不可以被继承。这样就可以避免被继承、被子类复写功能。
3)被final修饰的方法不可以被复写。
4)被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过“_”连接。
5)内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
Note:
1)final不能修饰构造函数。
2)static final 用来修饰成员变量和成员方法,可简单理解为“全局量”。对于变量,表示一旦给值就不可修改,并且通过类名可以访问。对于方法,表示不可覆盖,并且可以通过类名直接访问。
二、抽象类(abstract关键字)
1、定义:当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。
2、特点:
1)抽象方法一定在抽象类中。
2)抽象方法和抽象类都必须被abstract关键字修饰。
3)抽象类不可以用new创建对象。因为调用抽象方法没意义。
4)抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
说了这么多,下面用一个实例来说明抽象类的使用:
/*
假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:
姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个
奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方
法进行属性访问。
员工类:name id pay
经理类:继承了员工,并有自己特有的bonus。
*/
//员工类,也是父类
abstract class Employee
{
private String name;//姓名
private String id; //工号
private double pay; //工资
//自定义构造函数初始化
Employee(String name,String id,double pay)
{
this.name = name;
this.id = id;
this.pay = pay;
}
public abstract void work();//抽象的工作方法
}
//经理类,继承员工类
class Manager extends Employee
{
private int bonus;//特有的奖金属性
Manager(String name,String id,double pay,int bonus)//子类的构造方法
{
super(name,id,pay);//调用超类中的构造器
this.bonus = bonus;
}
public void work()//经理类的工作方法内容
{
System.out.println("manager work");
}
}
//普通员工类,继承员工类
class Commoner extends Employee
{
Commoner (String name,String id,double pay)
{
super(name,id,pay);
}
public void work()//普通员工类的工作方法内容
{
System.out.println("commoner work");
}
}
class AbstractDemo
{
public static void main(String[] args)
{
new Manager("manager","007",10000,2000).work();
new Commoner("commoner","012",5000).work();
}
}
3、抽象类与一般类的区别:
1)抽象类和一般类没有太大的不同。只是要描述的事物中出现了一些不知道具体内容的方法部分。这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体,所以通过抽象方法来表示。
2)抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法。
3)抽象类不可以实例化。
4)抽象类虽然不能创建对象,但是也有构造函数,供子类实例化调用。
Note:abstract 不能与 private、static、final 等同时修饰一个成员方法,因为:
final:被 final 修饰的类不能有子类。而被 abstract 修饰的类一定是一个父类。
private: 抽象类中的私有的抽象方法,不被子类所知,就无法被复写。而抽象方法出现的就是需要被复写。
static:如果 static 可以修饰抽象方法,那么连对象都省了,直接类名调用就可以了,可是抽象方法运行没意义。
三、接口
1、概述:初期理解,可以认为是一个特殊的抽象类当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。class用于定义类,interface 用于定义接口。
2、格式特点:
1)接口中常见定义:常量,抽象方法。
2)接口中的成员都有固定修饰符(接口中的成员都是public)。
常量:public static final
方法:public abstract
Note:
1)与类相同,接口也是一种数据类型。接口中的方法全部都是抽象方法。
2)使用关键字 interface
3)接口中的成员变量:一律用公共的、静态的、最终的,相应关键字可以省略不写。
4)成员变量相当于已被修饰为常量,必须在声明的时候赋值
5)接口中的成员方法:一律用公共的、抽象的,相应关键字可以省略不写。
6)接口并没有继承 Object 类,所有的接口都默认具备 Object 中的方法的抽象形式,以备给子类使用。
接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。否则子类是一个抽象类。接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。
3、接口的特点与相关说明
1)特点:
a)接口是对外暴露的规则,降低了耦合性,紧密联系在一起。
b)接口是程序的功能扩展
c)接口可以用来多实现(类与接口的关系是实现关系,类可以继承一个类的同时实现多个接口)
d)java 中只有接口与接口之间存在多继承。
2)相关说明:
a)如果一个类在实现接口时没有实现其中的全部抽象方法,那么这个类就是抽象类,必须用 abstract 关键字声明。
b)实现接口中的方法时应注意:接口中的抽象方法都是默认的 public 公共的,因此在实现接口的类中,重写接口的方法必须明确写出 pubilc 修饰符。这是因为继承关系中不允许缩小访问权限范围。
c)类可以在使用 extends 继承某一父类的同时使用 implements 实现接口。
d)类可以实现多个接口,用逗号将各接口名称分开即可。
e)接口之间用 extends 实现继承关系。子接口无条件继承父接口所有内容。
4、接口与抽象类的比较:
1)共性:都是不断向上抽取出来的抽象的概念。
2)区别:
a)抽象类体现继承关系,一个类只能单继承。
接口体现实现关系,一个类可以多实现。同时接口与接口之间有继承关系。
b)抽象类是继承,是 "is a "关系。
接口是实现,是 "like a"关系。|
c)抽象类中可以定义非抽象方法,供子类直接使用。
接口的方法都是抽象,接口中的成员都有固定修饰符。
d)抽象类中可以私有变量或方法。
接口中的常量和方法都是public修饰的权限。
以下演示接口的使用及相关特点:
interface Inter
{
public static final int NUM = 3;
public abstract void show();
}
interface InterA
{
public abstract void show();
}
class Demo
{
public void function(){}
}
class Test extends Demo implements Inter,InterA
{
public void show(){}
}
interface A
{
void methodA();
}
interface B //extends A
{
void methodB();
}
interface C extends B,A //接口与接口之间存在多继承
{
void methodC();
}
class D implements C
{
public void methodA(){}
public void methodC(){}
public void methodB(){}
}
class InterfaceDemo
{
public static void main(String[] args)
{
Test t = new Test();
System.out.println(t.NUM);
System.out.println(Test.NUM);
System.out.println(Inter.NUM);
}
}
结果如下所示:
四、多态
1、概述:
定义:多态可以理解为事物存在(具备)的多种体现形态。
体现:父类的引用指向了自己的子类对象。父类的引用也可以接收自己的子类对象。
前提:类与类之间必须有关系,继承、实现(接口);必须存在覆盖(或复写)
好处:多态的出现大大的提高了程序的扩展性。
弊端:虽然提高了扩展性,但只能使用父类的引用,去访问父类中的成员。
2、在多态中成员的特点:
a)(非静态)成员函数:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
Note:成员函数在多态调用时,编译看左边,运行看右边。
b)成员变量:无论编译和运行,都参考左边(引用型变量所属的类)。
c)(静态)成员函数:无论编译和运行,都参考左边。
3、类型转换
多态中往往是父类引用指向子类对象,这样就会出现类型的转换。
向上转型(类型提升,转成父类型):子类对象——>父类对象(程序会自动完成)
格式:父类 父类对象 = 子类实例;
向下转型:父类对象——>子类对象
格式:子类 子类对象=(子类)父类实例;
Note:发生向下转型关系之前必须先发生向上转型关系;对于向下转型时,必须明确的指明要转型的子类类型。此处要想知道类的类型用instanceof关键字判断。
4、instanceof:
用于判断某个对象是否是某种类型。
格式:对象名 instanceof 子类(实现)名
对象 intanceof 类型(类类型 接口类型) <前提是子类对象是有限的>
多态是自继承后类的又一大特性,并且使用时往往涉及到方法重载和方法覆盖,此处也作出一些比较。
5、方法重载与方法覆盖
方法重载与方法覆盖均是实现多态的机制。
重载方法必须满足的条件:
1)方法名必须相同
2)方法的参数列表必须不相同
3)方法的返回类型可以不相同
4)方法的修饰符可以不相同
5)方法重载可以在同一个类内部进行,也可以在子类里对父类的方法进行重载。
方法覆盖必须满足的条件:
1)子类方法的名称及参数表必须与所覆盖的方法相同
2)子类方法的返回类型必须与所覆盖方法相同
3)子类方法不能缩小所覆盖方法的访问权限
4)子类方法不能抛出比所覆盖方法更多的异常
5)方法覆盖限于子类对父类方法进行,不能在同一个类内部完成。
说了多态这么多的特点的使用,一下用代码演示:
/*
* 猫和狗都属于动物,使用多态完成猫和狗各自的动作
*/
abstract class Animal {
abstract void eat();
abstract void method();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("Cat eat");
}
@Override
public void method() {
System.out.println("吃鱼");
}
public void catchMouse() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("Dog eat");
}
@Override
public void method() {
System.out.println("啃骨头");
}
public void lookHome() {
System.out.println("看家");
}
}
public class DuotaiDemo {
public static void main(String[] args) {
Animal animal = new Cat();
animal.eat();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.lookHome();
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.catchMouse();
}
Animal animal2 = new Dog();
animal2.eat();
Dog dog = (Dog) animal2;
dog.lookHome();
}
}
结果如下所示:
本篇幅所描述的仅代表个人看法,如有出入请谅解。