黑马程序员_java面向对象(二) 继承

来源:互联网 发布:ubuntu 启动 黑屏 u盘 编辑:程序博客网 时间:2024/06/08 05:29

     

       ------- android培训、java培训、java学习型技术博客期待与您交流! ----------   


                 继承(Inherit

1  概述

       多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类只要继承(extends)那个类即可。

继承的类为子类(派生类),被继承的类为父类(超类基类)。子类会自动继承父类所有的方法和属性。

      作用:

       当我们定义一个类时,发现另一个类的功能这个类都需要,而这个类又要增加一些新功能时,就可以使用extends

关键字继承那个类,这样那个被继承类的功能就都有了,不必重写编写代码。

      只要在新类中编写新的功能即可,提高了代码的复用性。

      继承的出现让类与类之间产生了关系,提供了多态的前提。

2  特点:

       Java只支持单继承,不支持多继承,但是可以多重继承。如果一个类继承多个类,多个类中有相同的方法,子类调用

该方法时就不知道该调用哪一个类中的方法了。

      一个类只能有一个父类,不可以有多个父类:

class SubDemo extends Demo{} //Yes

class SubDemo extends Demo1,Demo2... //No

      java支持多层继承体系:

class A{}

class B extends A{}

class C extends B{}

        注意:不要仅为了获取其它类中某个功能而去继承,类与类之间要有所属(" is a")关系,BA的一种。

    成员变量

如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this;访问父类中的同名变量 用super

super的使用和this的使用几乎一致:

this代表的是本类对象的引用;super代表的是当前对象父类对象的引用。

    成员函数

        当子类出现和父类相同的函数时,子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。

这种情况是函数的另一个特性: 重写(覆盖)(override)

       子类对象实例化过程:

子类对象进行初始化时,父类的构造函数也会运行,因为子类的构造函数默认第一行有一条隐式的语句super()语句

它会访问父类中的空参数构造函数。而且子类中所有的构造函数默认第一行都是super(),在子类中第一行用this

键字去调其它的构造方法,这时系统将不再自动调父类的。但其它构造函数中会调用父类构造函数。

        继承细节:

在构造方法中thissuper关键字只能出现一次,而且必须是第一个语句。

        以后在设计类的时候,最好定义一个无参的构造方法,不然子类实例化的时候就容易出错。父类中没有空参构造

        函数,子类的构造函数必须通过this或者super语句指定要访问的构造函数。

子类不继承父类私有成员:父类中私有成员对外不可见,子类对象中无法访问这些成员。

构造函数不被继承:构造函数通常用来初始化类的成员变量。而父类和子类的成员变量,初始化方式、构造函数的名

  字都不相同。

    向上转型:

子类对象可以当作父类对象使用,因为父类有的功能子类都有。反之不能,因为子类有的父类不一定有。

定义一个父类类型的变量来记住子类对象,这在程序中称之为向上转型,

    强制类型转换:

把一个子类当做父类来用的时候,不能调用子类特有方法。因为编译时编译器会做语法检查,看到变量是父类类型

    就会到父类中查找是否有该方法,没有则报错。这种情况下,就需要将父类类型强转成子类类型。以(子类名)

    变量名形式进行强制类型转换

强制类型转换时,无论类型是否匹配编译都不会报错,但如果不匹配运行会报错,可以使用instanceof进行判断,

    判断是否是该类型。

子类当做父类来用时,不能调用子类特有方法,如果一定要调用,就需要强制类型转换回子类。

    在做转换时最好instanceof判断一下类型是否匹配。

3  函数覆盖(Override)

    子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。

    注意事项:

覆盖时,子类方法权限一定要大于等于父类方法权限;

静态只能覆盖静态:因为子类对象当做父类对象使用,父类对象中的方法在子类中必须都能获取到。

重写方法必须和被重写方法的方法名称、参数列表和返回值类型相同。子类方法返回值类型可以是父类方法返

    回值类型的子类。

在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。如果直接调用方法,先在当前子类中查找,

    如果子类有会调用子类的,使用super只在父类中查找,子类有没有都不调用;

重写方法时,不能比父类抛出更多的异常。子类只能比父类强,不能比父类弱。

父类中的私有方法不可以被覆盖。

    重载(Overload)和重写(Override)的区别:

重载是方法名相同,参数列表不同,和返回值类型无关。

重写是方法名、参数列表、返回值类型全相同。

    子类当做父类使用时需要注意:

当调用类的一个方法时,参数声明需要一个父类对象,可以将一个子类对象作为实参传递。此时方法的形参为父类,

在方法中使用父类变量调用方法时,其实是调用子类的方法。因为jvm会找到变量引用的地址,根据地址访问方法,

称为动态分配。这种机制没有被使用到类的成员变量上,如果用父类变量访问属性,会直接找父类的属性。

 

4  super关键字

    superthis的用法相同:

this代表本类对象的引用

super代表父类的内存空间的标识。

当子父类出现同名成员时,可以用super进行区分

子类要调用父类构造函数时,可以使用super语句。

    superthis的区别:

this : 

    代表对当前对象的引用

    使用this关键字引用成员变量。 

    使用this关键字在自身构造方法内部引用其他构造方法。 

    使用this关键字代表自身类的对象。 

    使用this关键字引用成员方法

super

    代表当前对象里面的父类的内存空间的标识。

    在子类的构造方法内部引用父类的构造方法。 

    在子类中调用父类中的成员方法。 

    在子类中调用父类中的成员变量。

5  final关键字

    final可以修饰类,方法,变量。

    final修饰的类不可以被继承。

    final修饰的方法不可以被覆盖。

    final修饰的变量是一个常量。只能被赋值一次。

    内部类只能访问被final修饰的局部变量。

    什么时候将变量修饰成final

通常在程序中使用常见的一些不会变化的数据.也就是常量值.比如3.14,这个数直接使用是可以的,但并不利于阅读,

    所以一般情况下,都会被该数据起个容易阅读的名称。

使用public static final共同修饰的常量就是全局常量。通常全部字母大写。double PI = 3.14;

    如果由多个单词组成每个单词间用下划线连接;

    final修饰变量赋值:

final修饰成员变量,必须初始化赋值,初始化有两种

    final int NUM = 15; //显示初始化

    NUM = 20; //错误,final修饰意味着不可以改变

    final int NUM; //构造函数初始化,但是不能两个一起初始化

    Demo() {

NUM = 15;

    }

    finalprivate小结:

        final修饰的类可以访问

            privateb不能修饰外部类,但可以修饰内部类,把外部类私有化是没有意义的

final修饰的方法不可以被子类重写

            private修饰的方法不可以被子类重写的,子类看不到父类的私有方法

        final修饰的变量只能在显示初始化或者构造函数初始化的时候赋值一次,以后不允许更改

    private修饰的变量,也不允许直接被子类或包中的其它类访问或修改,但可以通过setget方法进行访问

抽象类(abstract

    抽象定义:抽象就是从多个事物中将共性的,本质的内容抽取出来。

    抽象类:Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法。

    包含抽象方法的类就是抽象类。

    抽象方法的由来:多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,

    并未抽取功能主体。在功能声明,没有功能主体的方法称为抽象方法。

    例如:狼和狗都有吼叫的方法,可吼叫内容是不一样的。所以抽象出来的犬科虽然有吼叫功能,但是

    并不明确吼叫的细节。

    抽象类特点:

抽象方法一定在抽象类中

抽象方法和抽象类都必须被abstract关键字修饰

抽象类不可以用new创建对象,因为抽象类本身是不具体的,没有对应的实例。调用抽象方法也没有没意义

抽象类中的抽象方法要被使用,必须由子类复写其所有的抽象方法后,建立子类对象调用;

如果子类只覆盖了部分的抽象方法,那么该子类还是抽象类。

抽象类中可以有抽象方法也可以有非抽象方法

抽象类和一般类没有太大的不同,该如何描述事物,就如何描述事物,只不过,该事物出现了一些看不懂得东西。

    这些不确定的部分,也是该事物的功能,需要明确出现。但是无法定义主体

抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法抽象类不可以实例化。

特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

    什么时候定义抽象类:

        如果有多个类具有相同的方法声明,而方法的实现不一样,这时就可以抽象出父类,将方法在父类中声明;

    在设计软件时,要尽力抽象父类,继承关系以3~4层为宜

    抽象类中是否有构造函数?

只要是class定义的类里面就肯定有构造函数,抽象类中的函数是给子类实例化的;

    抽象关键字abstract不可以和哪些关键字共存?

final:如果方法被抽象,就需要被覆盖,而final是不可以被覆盖,所以冲突。

private:如果函数被私有了,子类无法直接访问,不能覆盖

        static : 不需要对象,类名即可以调用抽象方法。而调用抽象方法没有意义

7  模板设计模式(Template Pattern)

    定义:定义功能时,功能的一部分是确定且不允许更改的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,

  那么这时就将不确定的部分暴露出去,由该类的子类去实现。这种方式称为模板设计模式。

    为什么要使用模板方法设计模式:

在解决一些问题或者设计一个软件的时候,需要先定义一个模板,就相当于一种事先定义好的协议。

以后要做这系列的事情都按照这个模板来做。这样就实现统一化管理。

    如何实现模板方法设计模式:

定义一个抽象的父类做为模板,定义所有需要的方法;

在父类中实现供外界调用的主方法,将方法声明为final

根据不同业务需求定义子类实现父类的抽象方法;

class Demo {    public static void main(String[] args) {SubTemplate st = new SubTemplate();//主函数建立子类对象,调用继承自父类的模板方法st.method();    }}abstract class Template {//定义模板类,abstract修饰    public final void method() {//定义模板方法,final修饰run();//在模板方法中调用本类抽象方法    }    public abstract void run();}class SubTemplate extends Template {//子类extends模板类    public void run() {//复写抽象方法实现子类需要的功能....    }}





   

        ------- android培训、java培训、java学习型技术博客期待与您交流! ----------

原创粉丝点击