一.面向对象之继承
是将多个类的共性提取出来单独进行描述,通过继承的方式来建立类与类之间的关系。
子类继承父类中的所有成员。关键字extends。java语言只支持单继承,因为可能会带来安全隐患,造成代码冲突。但是支持多层继承,与多实现。
继承:
1,提高了代码的复用性
2,让类与类之间产生了关系。有了这个关系才有了多态的特性。
注意;千万不要为了获取其他类的功能,简化代码而继承。
必须是类与类之间有所属关系才可以继承。
继承体系的使用,查阅父类功能,创建子类对象使用功能。
子类中对父类中函数的覆盖重写
当子类与父类中函数一模一样的时候,当子类对象调用该函数,会运行子类函数的内容,如同父类的函数被覆盖一样。
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,功能内容却与父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容。
特点,
在对程序进行更新功能扩展时,就可以通过继承重写的方法对原功能进行修改,一般不对原程序进行修改,因为牵扯的地方太多。工作量过大。
super关键字,覆盖之后可以通过此方法调用父类中的方法,一般写在第一行。
注意
子类覆盖父类,必须保证子类权限大于或者等于父类权限,静态只能覆盖静态。
class A{//父类
A(){} public void eat(){ System.out.println("吃饭"); } public void say(){ System.out.println("我是A的方法"); } } class B extends A{//子类
B(){
super();//默认子类的构造方法调用父类的空参构造方法进行初始化,如果父类中没有空参的构造方法需要对其指定有参的父类构造方法
} public void say(){//对父类中的方法进行复写 System.out.println("我是B的方法"); } public void run(){//增加新的功能方法对父类进行扩展 System.out.println("我是B我还会跑"); } } class Test{ public static void main(String[]args){ A a=new A(); B b=new B(); a.eat(); b.eat();//调用从父类中继承的方法 a.say(); b.say(); } }
关于访问权限
public>default>private
子类在实例化对象的时候,首先调用的是父类构造函数然后是调用本类构造函数,在所有子类构造函数中默认第一行是有隐式super()语句的;当父类中没有空参构造函数的时候,必须手动将super语句更改为对应的有参构造函数。当然子类中可以通过this()调用本类中其他的构造函数,若果这个函数调用了父类的构造函数就不需要再写入super()语句。
为什么子类中的一定要访问父类中的构造函数,因为父类中的数据子类可以直接获取,所以子类对象在建立的时候,需要先访问父类查看父类是如何对这些数据进行初始化的。
另外当父类属性成员被private修饰时,子类时无法访问的必须借用父类的构造方法。
final 关键字
1,final可以修饰类,变量,函数
2.被final修饰的类不可以被继承。。
3,倍final修饰的方法不可以被覆盖重写以保证子类不需要功能的封装性。
4,倍final修饰的变量只能赋值一次,既可以修饰成员变量又可以修饰局部变量。
挡在描述事物时一些数据的出现值是固定的,那么这时为了增强阅读性,对其进行特定的命名,当不需要再改变此变量的时候用final修饰作为常量,常量的书写规范所有字母都大写,有多个单词组成的时候每个单词之间用下划线连接。
二.抽象类,关键字abstract
抽象类的由来是由事物中功能的共性向上进行提取出现的,功能名称相同但是功能主体不同,此时定义成抽象方法。
抽象类的特点
抽象方法一定定义在抽象类中,抽象类中可以有非抽象方法,也可以不定义抽象方法,不让建立对象。
抽象类不可以用new创建对象,因为调用抽象方法没有意义
抽象类中的方法要被调用,必须有子类复写所有的抽象方法之后,建立类对象调用。
如果子类只覆盖了部分抽象方法,则子类仍然是抽象类。
抽象类虽然不能创建对象但是是有构造函数的,是要给子类使用的。
由于抽象类的的继承特点,子类要能够创建对象就必须全部重写父类的抽象方法,这样就实现了功能模块的强制性。
抽象类与一般类的区别
就是多了个抽象函数的定义,以及不能实例化。
模板方法模式;
在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在不确定的部分中,那么这时候就将不确定的部分进行暴露出去。由该类的子类去完成。
abstract class GetTime{ public final void getTime(){//此处用final修饰不让子类继承 long start=System.currentTimeMillis(); runCode(); long end=System.currentTimeMillis(); System.out.println("毫秒:"+(end-start)); } public abstract void runCode();//此处是将测试部分代码抽象封装由子类继承后复写 } class SubTime extends GetTime{ public void runCode(){ //测试代码 } }
三.接口;关键字interface,implements
接口中的成员修饰符都是固定的
成员常量:public static final
成员函数;public abstract
接口的出现将多继承通过另一种形式体现出来。即多实现。
接口:类似特殊的抽象类,是不能创建对象的,需要被子类全部实现抽象方法。
接口可以被类多实现,一个类可以实现多接口。因为没有方法主体对于冲突的功能也只需要重写一次即可,解决了继承的局限性。
接口之间的关系,接口是可以继承的而且支持多继承,也是因为其方法并没有方法主体。
接口的特点
1,接口是对外暴露的规则
2,接口是程序的功能扩展
3,接口可以用来多实现
4,类与接口之间是实现关系,而且类可以继承一个雷的同事实现多个接口。
5,接口与接口之间可以有继承关系。
三.多态
某一类事物具有的多种形态,类与实体对象的关系到实体对象与类和父类的关系。
父类的引用指向子类对象就是多态的代码表现形式。
多态通过继承大大提高了代码的可扩展性。
多态的前提是类与类之间必然有继承或者实现的关系。
多态的弊端是只能使用父类的引用访问父类中存在的共性成员
abstract class Animal{ 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 DuoTai{
public static void main(String []args){
Animal a =new Cat();//类型提升,向上转型。
Animal b=new Dog();
Cat c=(Cat)a;//类型强转换,向下转型。前提是经历过向上转型,即本来就是此类型。这句话也可以写入function功能中但是要加入判断语句确定具体的类型,instanceof关键字用于判断所属类型。
function(a);
function(b);
}
public void function(Animal a){//将共性行为通过多态提取出来提高了代码的复用性。也可以定义工具类对其进行单独的封装。
a.eat();
}
}
此时如果新出现其他Animal的子类或者同一类多个对象的时候只要直接调用Function方法就可以执行eat方法。对象父子类的继承体系,工具类对对象类的调用,主函数最终使用者。所有这些都是基于面向对象的封装为基础,通过继承与多态关系建立程序结构网络。
多态成员的特点
注意看调用方法的对象引用,如果是父类的引用则看弗雷中是否有该方法,没有的话则不能编译,需要判断类型转化为子类的引用。如果有的话则参考下面的规则。编译都是看引用,运行时只有非静态成员函数是看所属的类,成员变量静态成员都是看引用。
在多态中非静态成员函数的特点在编译时期,参阅引用型变量所属的类中是否有调用的方法,如果由则编译通过,没有编译失败,在运行期参阅对象所属的类中是否有调用方法。
编译靠父类,运行靠子类。
在多态中成员变量的特点,无论编译和运行,都参阅左边的引用型类为依据。
在多态中静态成员函数的特点,无论编译和运行,都参阅左边的引用类型为依据。
三.内部类访问规则
将一个类定义在另一个类里面,对立面那个类就成为内部类。可以被成员修饰符所修饰,比如private私有,static静态。
访问特点
内部类可以直接访问外部类中的成员,包括私有成员。而外部类要访问内部类中的成员必须要建立内部类的对象。从外部放问外部类中的内部类时,需要先建立其对象,格式为Outer.Inner in=new Outer().new Inner();
之所以内部类中可以直接访问外部类中的成员,是因为内部类可以直接持有外部类的引用,格式为外部类名.this.成员
在外部其他类中,访问静态内部类中的非静态成员
new Outer.Inner().function();
在外部其他类中访问静态内部类中的静态成员
Outer.Inner.function();
党内部类中定义了静态成员,该内部类必须是静态的static
当外部类中的静态方法访问内部类时,内部类也必须是static的。
内部类的定义
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事务在使用外部事物。
以上内部类都是些在成员位置的,如果写在局部位置如方法体内,是不能被成员修饰符修饰的。
可以直接访问外部类中的成员,但是不能访问该局部的变量,只能访问final修饰的局部变量。
匿名内部类就是内部类的简写格式。
定义匿名内部类的前提
内部类必须是集成一个类或者实现接口。
匿名内部类的格式如下;new 父类或者接口(){定义子类的内容}
其实匿名内部类就是一个匿名子类对象。是一种表现形式。
class Outer{ int x=3; public void function(){ new AbsDemo(){//匿名内部类。AbsDemo是父类。 void show(){ System.out.println(); } }.show(); } }
匿名内部类中定义的方法最好在两个之内
匿名内部类其实就是用匿名类去代替外部类成员或者成员方法的方法体。将其当做一个整体来更能帮助理解。