1, 继承的原理:
通过定义简单而通用的类,称为父类,然后把这些类的功能派生成更详细更复杂的类,称为子类。子类拥有父类所有的功能和特性,此外还有自己新定义的额外的功能和特性。
例如: 地产开发商,要盖楼。首先是找个设计者设计楼房蓝图,然后就按照这个蓝图去盖楼。许多楼房根据同一张蓝图完成建筑施工,它们是位于不同地方的相同楼房,有不同的人居住。假设现有客户要一套新住房,它与现有的楼房类似,但是又有某些差别和新增的特点,客户要求以原有蓝图为基础,进行一些修改以满足客户的需求。之后开发商就会在原有蓝图的基础上,按照客户的要求来修改新增一些客户所要求的东西。这就是继承机制。 2,如何正确理解继承
(1)继承有一条原则:用继承表示is-a关系(分类关系)。
(2)想要理解继承的用法必须知道is-a的含义。
is-a表达的含义:如果子类型的每一个对象都可以看作是父类型的对象,那么子类是从父类继承的。
例如:每只喜鹊都是鸟,那么喜鹊是一种鸟。
(3)把继承作为一种分类法来看待。在分类结构中,层次越高的类,所表示的概念越抽象;层次越低的类所表示的概念越特殊。如果是在面向对象中,就意味着子类相对父类拥有更多的方法。
代码:
//人类3,继承有什么好处:
class Person
{
String name;
int age;
}
//学生类继承人类
class Student extends Person
{
//学生类的学习方法
void study()
{
System.out.println("good study");
}
}
//工人类继承人类
class Worker extends Person
{
//工人类的工作方法
void work()
{
System.out.println("good work");
}
}
class ExtendsDemo
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
(1)提高了代码的重用性
使用继承可以减少很多重复劳动和多余的代码,创造出易于理解的可重用的组件。
(2)让类与类之间有了关系,有了这个关系才有了多态的特性。
4,子父类出现后,类中成员的特点
(1)变量
如果子类中出现非私有的同名成员变量时,子类要访问本类中变量,用this。子类要访问父类中的同名变量,用super。
(2)子父类中的函数
当子类出现和父类一模一样的函数时,当子类对象调用该函数时,会运行子类函数的内容。相当于父类的函数被子类覆盖了。
当子类继承父类,沿袭了父类的功能到子类中,但是子类虽然具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖的特性,保留父类的功能定义,并重写功能内容。
代码:
class Fu(3)子父类中的构造函数
{
//父类的睡觉方式
public void sleep()
{
System.out.println("躺着睡");
}
}
class Zi extends Fu
{
//子类的睡觉方式
public void sleep()
{
System.out.println("趴着睡");
}
}
在对子类对象进行初始化时,父类的构造函数也会运行。那是因为子类的构造函数默认第一行有一条隐式的语句super();
super():会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函呢?
因为父类中的数据子类可以直接获取,所以子类对象在建立时需要查看父类是如何对这些数据进行初始化的。所以,子类在对象初始化时,要先访问一下父类中的构造函数。
5,继承关系下的初始化顺序:
父类静态-->子类静态-->父类非静态-->父类构造-->子类非静态-->子类的构造。
6,抽象类:
(1) 在一个继承体系中,会有这样一种情况存在,即希望让一个父类不完整而让子类去填补父类留下的空隙,这时就需要使用抽象类。
(2)怎么判断要不要使用抽象类呢?
当一个对象的父类只是一个概念或是一个无形对象(如哺乳动物,脊椎动物等)时,使用抽象类是一种较好的方法。
代码:
//雇员抽象类(3)抽象类的特点
abstract class Employee
{
//抽象方法
public abstract void work();
}
//员工类继承雇员类
class Pro extends Employee
{
//实现父类的抽象方法。
public void work()
{
System.out.println("Pro work");
}
}
抽象类中的成员方法:和类中的成员方法没有区别。
抽象方法:被abstract关键字修饰的方法叫抽象方法,用分号取代方法体。
public abstract void work();
抽象方法和类的关系:包含抽象方法的类一定是抽象类,抽象类中不一定包含抽象方法。 抽象方法的注意事项:不能被static,private,final关键字修饰。
成员方法:都是实现方法可以,都是抽象方法也可以,部分实现部分不实现也可以。记住:部分实现。
构造方法:初始化功能。
7,接口
初期理解,可以认为是一个特殊的抽象类,当抽象类中方法都是抽象的,那么可以用接口来表示。
(1)接口的特点
接口是一个特殊的类,它只有方法定义而没有实现,实现任务完全交给子类来完成。
接口以interface标志
继承接口用implements关键字实现。
接口可以继承接口
接口可以有成员,成员变量:public static final 修饰。成员方法:public abstract修饰。
public:让所有实现类都可以使用。
static:静态属于类,如果不加static,接口又不能创建对象。
fianl:修饰的是常量,意义在于不让实现类去修改,如果不加final,那么实现都能修改,没意义。
接口没有构造函数,不能创建对象。
接口给java提供了多继承机制
代码:
//接口8,类,抽象类,接口的区别
interface Inter
{
//成员变量
public static final int NUM =3;
//成员方法
public abstract void show();
}
//接口
interface InterA
{
//成员方法
public abstract void method();
}
//类
class Demo
{
//成员方法
public void funtion(){};
}
//test类继承了demo类并且实现了两个接口
class Test extends Demo implements Inter,InterA
{
//实现接口的方法
public void show(){}
//实现接口的方法
public void method(){}
}
//测试类
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);
}
}
接口 | 抽象类 | 类 | |
标志 | interface | abstract class | class |
如何继承 | implements | extends | extends |
可以继承 | 接口 | 抽象类,类 | 抽象类,类 |
可以实现 | 无 | 一个或多个接口 | 一个或多个接口 |
有否成员变量 | 只有static final成员 | 都可 | 都可 |
是都有构造函数 | 无 | 有 | 有 |
能不能实例化 | 不能 | 不能 | 能 |
意图,作用 | 规范行为,强制实现 | 继承成员+规范行为,强制实现 | 继承成员 |
(二)多态 多态:即事物存在的多种形态。例如:人,男人,女人。动物,猫,狗。药,有胶囊,有药片。
例如:某款游戏中有九大职业,它们都具备游戏人物的一些共性的属性和行为。但是它们的形态不同,有的是兽人,有的精灵,有的是狼人,有的是人类,并且它们都有自己特有的一些技能。 1,多态分为:类内部多态,继承多态。
类内部多态:即重载。继承多态:即重写。 代码:
abstract class Animal//动物抽象类,2,在多态中成员的特点
{
//抽象方法。即:是规则,每个动物都有吃的方法。
public abstract void eat();
}
//猫类继承动物抽象类
class Cat extends Animal
{
//实现了父类的方法
public void eat()
{
System.out.println("吃鱼");
}
//子类特有的方法
public void catchMouse()
{
System.out.println("抓老鼠");
}
}
//狗类继承动物类
class Dog extends Animal
{
//实现了父类的方法
public void eat()
{
System.out.println("吃骨头");
}
public void kanJia()//子类特有的方法
{
System.out.println("看家");
}
}
//猪类继承了动物类
class Pig extends Animal
{ //实现了父类的方法
public void eat()
{
System.out.println("饲料");
}
public void gongDi()//子类特有的方法
{
System.out.println("拱地");
}
}
分开
class DuoTaiDemo2
{
public static void main(String[] args)
{
Animal a = new Cat();//类型提升,向上转型
a.eat();
//如果想要调用猫的特有方法时,如何操作?
//强制将父类的引用,转成子类类型。向下转型。
Cat c = (Cat)a;
c.catchMouse();
-----------------------------------------------------------------------------------
//千万不要出现这样的操作,就是将父类对象转换成子类类型。
//我们能转换的是父类引用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。
//多态自始至终都是子类对象在做着变化
//Animal a = new Animal();
//Cat c = (Cat)a;
-----------------------------------------------------------------------------------
}
//用于接受对象的方法
public static void function(Animal a)//Animal a = new Cat();
{
a.eat();
if (a instanceof Cat)
{
Cat c = (Cat)a;
c.catchMouse();
}
else if (a instanceof Dog)
{
Dog d = (Dog)a;
d.kanJia();
}
}
}
代码:
class Fu//父类(1)在多态中成员变量的特点:
{
int num = 5;//父类非静态成员变量
void method1()//父类方法1
{
System.out.println("fu method_1");
}
void method2()//父类方法2
{
System.out.println("fu method_2");
}
}
class Zi extends Fu//子类继承父类
{
int num = 8;//子类非静态成员
void method1()//子类方法1
{
System.out.println("zi method_1");
}
void method3()//子类方法2
{
System.out.println("zi method_3");
}
}
//测试类
class DuoTaiDemo4
{
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num);//5
Zi z = new Zi();
System.out.println(z.num);//8
}
}
无论编译和运行,都参考左边(引用类型变量所属的类)。
Fu f = new Zi();
System.out.println(f.num);//5
Zi z = new Zi();
System.out.println(z.num);//8
(2)在多态中成员函数的特点:
在编译是时期:参阅引用变量所属的类中是否有调用方法,如果有,编译通过。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单说:成员函数在多态调用时,编译看左边,运行看右边。
(3)在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
小总结 继承:
个人认为继承是在通过减少完成项目所需要的代码量,来保持项目的可管理性。
使用继承可减少很多重复代码的书写,做出来的东西是易于理解的可重用组件。
多态:
可以通过父类来定义对象的形式,并提供对象的默认实现方法,而子类在根据这个默认的实现的方法进行修改,来更好的适应具体的要求。因此,定义一个接口可以作为多个不同实现的基础,在接口的帮助下,可以将类的方法和实现完全分离。