Java面向对象04

1.继承

继承由来

通过代码演示描述多个事物。多个事物之间发现有共同的属性和行为。那么代码的复用性很差,那么怎么办呢br> 可以将相同的代码进行抽取,抽取出来后放在单独的类中。

代码抽取到了Person类中,但是Student和Worker类与Person类没有任何关系,那么Student和Worker类如何能使用到Person中的name和age属性。

为了让类与类之间能有关系,需要使用Java中提供的继承这种机制。继承需要用到关键字extends。

继承的好处

  1. 继承的出现提高了代码的复用性,提高软件开发效率。
  2. 继承的出现让类与类之间产生了关系,提供了多态的前提。

2.单继承与多继承

继承让类与类之间产生了关系,那到底什么时候使用继承呢br> 使用继承,必须保证类与类之间有所属(is a)关系,即xxx是zzz中的一种。例如:苹果是水果中的一种,狗是犬科中的一种
Java只支持单继承,不支持多继承。一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2…//error
Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
定义继承需要注意
不要仅为了获取其他类中某个功能而去继承。
日常开发中小技巧
多层次继承出现的继承体系中,通常看父类中的功能,了解该体系的基本功能,建立子类对象即可使用该体系功能。
多继承虽然能使子类同时拥有多个父类的特征,但是其缺点也是很显著的,主要有两方面:
(1)如果在一个子类继承的多个父类中拥有相同名字的实例变量,子类在引用该变量时将产生歧义,无法判断应该使用哪个父类的变量。
(2)如果在一个子类继承的多个父类中拥有相同方法,子类中有没有覆盖该方法,那么调用该方法时将产生歧义,无法判断应该调用哪个父类的方法。

3.子父类中成员变量的特点

了解了继承给我们带来的好处,提高了代码的复用性。继承让类与类或者说对象与对象之间产生了关系。当继承出现后,类的成员之间产生了那些变化呢br> 类的成员重点学习成员变量、成员函数和构造函数的变化。

成员变量:如果子类父类中出现不同名的成员变量,这时的访问是没有任何问题。

代码说明:Fu类中的成员变量是非私有的,子类中可以直接访问,若Fu类中的成员变量私有了,子类是不能直接访问的。
当子父类中出现了同名成员变量时,在子类中若要访问父类中的成员变量,必须使用关键字super来完成。

当程序执行new Zi();这时会加载Zi类字节码文件,但由于Zi类继承了Fu类,因此需要将父类字节码文件加载进方法区。当Zi和Fu的字节码加载完毕后。会执行new Zi();即在堆内存中创建Zi类对象,并为其分配内存地址0x99;对象的内存空间分配结束之后,开始成员变量默认初始化,此时需要注意Fu的num同样也会在此对象中。紧接着开始zi构造函数压栈,在zi的构造函数中有隐式的super()语句,此时Fu的构造函数也会压栈,Fu的构造函数压栈后会将Fu的num显示初始化。接着Fu构造函数弹栈,执行Zi的构造函数,Zi的num显示初始化。接着Zi构造函数弹栈。此时Zi对象在堆中创建完成,并将内存地址0x99赋值给
main方法中的z引用。接着调用zi的show方法,show方法压栈。

注意:super和this的用法相似,this:代表本类的对象引用。super:代表的父类内存空间,而不是父类的引用。子父类中同名的成员变量,这种情况开发中不用,因为父类一旦描述完成了属性,子类直接使用就可以了。

4.子父类中成员函数的特点

当在程序中通过对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法

成员方法特殊情况——覆盖
子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖。

覆盖的应用
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容。

举例:比如手机,当描述一个手机时,它具有发短信,打电话,显示来电 码功能,后期由于手机需要在来电显示功能中增加显示姓名和头像,这时可以重新定义一个类描述手机,并继续原有的描述手机的类。并在新定义的类中覆盖来电显示功能,在其中增加显示姓名和头像功能。

5.重写的注意事项

重写需要注意的细节问题

  1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限
  2. 静态只能覆盖静态,或者被静态覆盖,意思就是 静态函数不存在重写!
  3. 写法上稍微注意:必须一模一样:函数的返回值类型 函数名 参数列表都要一样
    总结:
    当一个类是另一个类中的一种时,可以通过继承,来扩展功能;
    如果父类具备的功能内容需要子类特殊定义时,使用重写。

6.子父类中构造函数的特点

在创建子类对象时,父类的构造函数会先执行,因为子类中所有构造函数的第一行有默认的隐式super();语句,调用本类中的构造函数用this(实参列表)语句,调用父类中的构造函数用super(实参列表)。
为什么子类对象初始化都要访问父类中的构造函数为子类继承了父类的内容,所以创建对象时必须要先看父类是如何对内容进行初始化的。

执行结果:
Fu构造函数0
Zi构造函数4
子类中的构造函数为什么有一句隐式的super()呢br> 原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。才可以更方便的使用父类中的内容。
当父类中没有空参数构造函数时,子类的构造函数必须有显示的super语句指定要访问的父类中的构造函数。

7.子类实例化过程的细节

如果子类的构造函数第一行写了this调用了本类其他构造函数,那么super调用父类的语句还有吗br> 这时是没有的,因为this()或者super(),只能定义在构造函数的第一行,因为初始化动作要先执行。
父类构造函数中是否有隐式的super呢是有的。记住:只要是构造函数默认第一行都是super();
父类的父类是谁呢uper调用的到底是谁的构造函数呢br> Java体系在设计,定义了一个所有对象的父类Object 。
注意:
类中的构造函数默认第一行都有隐式的super()语句,在访问父类中的构造函数。所以父类的构造函数既可以给自己的对象初始化,也可以给自己的子类对象初始化。如果默认的隐式super语句没有对应的构造函数,必须在构造函数中通过this或者super的形式明确调用的构造函数。

8.final关键字

继承的出现提高了代码的复用性,并方便开发。但随之也有问题,有些类在描述完之后,不想被继承,或者有些类在中的部分方法功能是固定的,子类不能重写。可是当子类继承了这些特殊类之后,就可以对其中的方法进行重写,那怎么解决呢br> 要解决上述的这些问题,需要使用到一个关键字final,final的意思为最终,不可变。
final是个修饰符,它可以修饰类,类的成员,以及局部变量。
● final修饰类不可以被继承,但是可以继承其他类
● final修饰的方法不可以被覆盖,但父类中没有被final修饰方法,子类覆盖后可以加final
● final修饰的变量称为常量,这些变量只能赋值一次,定义的时候必须有初始值
● final修饰的引用类型变量,表示该引用变量的引用不能变,而不是引用所指的对象中的数据还是可以变化的
什么时候会在程序中定义final常量呢/strong>
当程序中一个数据是固定不变的,这时为了增加阅读性,可以给该数据起个名字。为了保证这个变量的值不被修改,加上final修饰,变量就为阅读性很强的常量。书写规范,被final修饰的常量名所有的字母都是大写的。如果由多个单词组成单词间通过 _ 连接。
通常规范中:常量名称所有字母大写,若有多个单词组成,单词间使用下划线连接。
public static final修饰的常量称为全局常量;
public static final double PI = 3.14159265358979323846;
public static final String APP_SEPARATOR = “/”;

9.抽象类

抽象类由来
当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。

但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。比如一个图形类应该有一个求周长的方法,但是不同的图形求周长的算法不一样。那该怎么办呢/p>

分析事物时,发现了共性内容,就出现向上抽取。会有这样一种特殊情况,就是功能声明相同,但功能主体不同。那么这时也可以抽取,但只抽取方法声明,不抽取方法主体。那么此方法就是一个抽象方法。

描述狗:行为:吼叫
描述狼:行为:吼叫
狗和狼之间有共性,可以进行向上抽取。抽取它们的所属共性类型:犬科。由于狗和狼都具有吼叫功能,但是他们具体怎么吼叫却不一样。这时在描述犬科时,发现了有些功能(吼叫)不具体,这些不具体的功能,需要在类中标识出来,通过java中的关键字abstract(抽象)。

当定义了抽象函数的类也必须被abstract关键字修饰,被abstract关键字修饰的类是抽象类。

抽象类的特点

  1. 抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
  2. 抽象类不可以创建实例,原因:调用抽象方法没有意义。
  3. 只有覆盖了抽象类中所有的抽象方法后,其子类才可以实例化。否则该子类还是一个抽象类。

之所以继承,更多的是在思想,是面对共性类型操作会更简单。
细节问题

  1. 抽象类一定是个父类br> 是的,因为不断抽取而来的。
  2. 抽象类是否有构造函数br> 有,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。
    抽象类和一般类的异同点:
    相同:
    ● 它们都是用来描述事物的。
    ● 它们之中都可以定义属性和行为。
    不同:
    ● 一般类可以具体的描述事物。抽象类描述事物的信息不具体
    ● 抽象类中可以多定义一个成员:抽象函数。
    ● 一般类可以创建对象,而抽象类不能创建对象。
  3. 抽象类中是否可以不定义抽象方法。
    是可以的,那这个抽象类的存在到底有什么意义呢仅是不让该类创建对象。
  4. 抽象关键字abstract不可以和哪些关键字共存br> ● final:fianl修饰的类是无法被继承的,而abstract修饰的类一定要有子类.final修饰的方法无法被覆盖,但是abstract修饰的方法必须要被子类去实现的。
    ● static:静态修饰的方法属于类的,它存在与静态区中,和对象就没关系了。而抽象方法没有方法体,使用类名调用它没有任何意义。
    ● private:私有的方法子类是无法继承到的,也不存在覆盖,而abstract和private一起使用修饰方法,abstract既要子类去实现这个方法,而private修饰子类根本无法得到父类这个方法。互相矛盾。

10.接口

当一个抽象类中的所有方法都是抽象方法时,那么这个抽象类就可以使用另外一种接口这种机制来体现。
接口怎么定义呢义普通的类或者抽象类可以使用class关键字,定义接口必须interface关键字完成。

接口中成员的特点

  1. 接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量。
  2. 接口中可以定义方法,方法也有固定的修饰符,public abstract
  3. 接口中的成员都是公共的。
  4. 接口不可以创建对象。
  5. 子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。

接口最重要的体现:解决多继承的弊端。将多继承这种机制在java中通过多实现完成了。

怎么解决多继承的弊端呢/strong>
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
为什么多实现就解决了呢br> 因为接口中的功能都没有方法体,由子类来明确。
类继承类同时实现接口
子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢时通过实现接口来完成。

接口的出现避免了单继承的局限性。父类中定义的事物的基本功能。接口中定义的事物的扩展功能
接口多继承
多个接口之间可以使用extends进行继承。

在开发中如果多个接口中存在相同方法,这时若有个类实现了这些接口,那么就要实现接口中的方法,由于接口中的方法是抽象方法,子类实现后也不会发生调用的不确定性。
没有抽象方法的抽象类的由来
在开发中,若一个接口中有多个抽象方法,但是实现这个接口只使用其中某些方法时,这时我们仍然需要将其他不使用的方法实现,这样明显不符合我们的要求,但不实现这些方法又不行。那么怎么办呢以使用一个抽象类,作为过度,而这个抽象类实现这个接口,所有方法都以空实现存在。这就是没有抽象方法的抽象类的存在价值。我们只要继承这个抽象类,覆盖其中需要使用的方法即可。

//拥有多个方法的接口interface Inter{void show();void show1();void show2();void show3();}//作为过度的抽象类,此类将接口的所有方法都实现,这里的实现是空实现abstract class AbsInter implements Inter{public void show(){}public void show1(){}public void show2(){}public void show3(){} }/*//此类直接实现Inter,但只使用其他show和show2方法,这样导致其他两个方法也要实现//不符合我们的要求class SubInter2 implements Inter{public void show() { System.out.println("show");}public void show1() {}public void show2() { System.out.println("show2");      }public void show3() {}}*/

                                                        

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年4月8日
下一篇 2019年4月8日

相关推荐