1.继承
你会发现Dog和Cat中有许多重复的地方,那能否将这些共性抽取呢?面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。
( 继承的概念)承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性 的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。 例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。如图:
1.2继承的语法
在Java中如果要表示类之间的继承关系,需要借助extends关键子:
修饰符 class 子类 extends 父类 {
// ...
}
注意:
1. 子类会将父类中的成员变量或者成员方法继承到子类中了
2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
1.3父类的成员访问
public class Base {
int a;
int b;
}
public class Derived extends Base{
int c;
public void method(){
a = 10; // 访问从父类中继承下来的a
b = 20; // 访问从父类中继承下来的b
c = 30; // 访问子类自己的c
}
}
1.3.1 子类和父类成员变量同名
public class Base {
int a;
int b;
int c;
}
/
public class Derived extends Base{
int a; // 与父类中成员a同名,且类型相同
char b; // 与父类中成员b同名,但类型不同
public void method(){
a = 100; // 访问父类继承的a,还是子类自己新增的a?
b = 101; // 访问父类继承的b,还是子类自己新增的b?
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}
1.3.2成员方法名相同
public class Base {
public void methodA(){
System.out.println("Base中的methodA()");
}
public void methodB(){
System.out.println("Base中的methodB()");
}
}
public class Derived extends Base{
public void methodA(int a) {
System.out.println("Derived中的method(int)方法");
}
public void methodB(){
System.out.println("Derived中的methodB()方法");
}
public void methodC(){
methodA(); // 没有传参,访问父类中的methodA()
methodA(20); // 传递int参数,访问子类中的methodA(int)
methodB(); // 直接访问,则永远访问到的都是子类中的methodB(),基类的无法访问到
}
}
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到 则访问,否则编译报错。 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;
1.4初始化
classPerson{
publicStringname;
publicintage;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
System.out.println("构造方法执行");
}
{
System.out.println("实例代码块执行"); }
static{
System.out.println("静态代码块执行"); }
}
publicclassTestDemo{
publicstaticvoidmain(String[]args){
Personperson1=newPerson("wcy1",10);
System.out.println("============================");
Personperson2=newPerson("wcy",20);
}
}
结果为:
静态代码块执行实例代码块执行构造方法执行============================实例代码块执行构造方法执行
而通过以上分析可以得出:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行
而主要分为三种:
JAVA当中不支持多继承
时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到 一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会 更加复杂. 但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层 次太多, 就需要考虑对代码进行重构了. 如果想从语法上进行限制继承, 就可以使用 fifinal 关键字
2.多态
2.1多态的概念
2.2多态实现的条件
在 java 中要实现多态,必须要满足如下几个条件,缺一不可:1. 必须在继承体系下2. 子类必须要对父类中方法进行重写3. 通过父类的引用调用重写的方法多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法。
class Animal {
public void eat() {
System.out.println("动物吃东西");
}
}
class Cat extends Animal {
public void eat() {
System.out.println("猫在吃猫粮");
}
public void catAction() {
System.out.println("猫把你的花瓶打碎 沙发扯破 乱拉尿拉屎 扯坏窗帘还咬你");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Cat(); // 向上转型
animal.eat(); // 调用父类的eat方法,输出“猫在吃鱼”
}
}
这个其实也是称多态访问(也叫运行访问), 这个代码在运行时才会调用子类重写的eat()函数,也被成为动态访问。而且需要进行一个向上转型,可以从左向右看猫是一个动物没错吧?其实向下转型就是把它俩顺序调一调,也是从左看,这里我们就需要把父类强转了,因为动物不一定是猫,所以你要把它转到猫,这样子也就是向下转型了,其实它很危险要少用。
2.3重载和重写的区别
重写的原则:
对于已经投入使用的类,尽量不要进行修改。最好的方式是:重新定义一个新的类,来重复利用其中共性的内容,并且添加或者改动新的内容。例如:若干年前的手机,只能打电话,发短信,来电显示只能显示号码,而今天的手机在来电显示的时候,不仅仅可以显示号码,还可以显示头像,地区等。在这个过程当中,我们 不应该在原来老的类上进行修改,因为原来的 类,可能还在有用户使用 ,正确做法是: 新建一个新手机的类,对来电显示这个方法重写就好了,这样就达到了我 们当今的需求了 。