zoukankan      html  css  js  c++  java
  • 04_Java面向对象特征之继承与多态

    1. 继承

         Java继承的实现(只支持单继承,而不是多继承,但有接口的多实现)         

        多个类中存在相同属性和行为时,将这些内容抽取到单独一个类. 定义类时直接通过extends关键字指明要继承的父类.子类对象除了可以访问子类中直接定义的成员外,也可访问父类的所有非私有成员.能否直接访问父类私有成员则取决于访问权限设置.

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

        继承提高了代码的复用性。

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

      如何使用一个继承体系中的功能:

        查阅父类功能(定义了共性的功能)

        创建子类对象使用功能(因为父类可能不能创建对象, 而且子类提供了更丰富的功能) 

       继承中自子类变量的特点:

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

       继承中函数的特点:    

        函数覆盖(Override)
        子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为重写或者复写。
        父类中的私有方法不可以被覆盖。
        在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。
        覆盖注意事项:
          • 覆盖时,子类方法权限一定要大于等于父类方法权限
          • 静态只能覆盖静态。
        覆盖的应用:
          • 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内

         构造方法在类继承中的作用

              构造方法不能继承.由于子类对象要对来自父类的成员进行初始化,因此,在创建子类对象时除了执行子类的构造方法外,还需要调用父类的构造方法.具体遵循如下原则:

              (1) 当子类未定义构造方法时,创建对象时将无条件地调用父类的空构造方法,以为每行第一条super(); 

              (2) 对于父类的含参数构造方法,子类可以在自己构造方法中使用关键字super来调用它,但super调用语句必须是子类构造方法中的第一个可执行语句; 

              (3) 子类在自己定义构造方法中如果没有用super明确调用父类的构造方法,则在创建对象时,将自动先执行父类的无参构造方法,然后再执行自己定义的构造方法。 

              所以在一个类的设计时如果有构造方法,最好提供一个无参构造方法.因此,系统类库中的类大多提供了无参构造方法,用户编程时最好也要养成此习惯.

         【注意】使用this查找匹配的方法时首先在本类查找,找不到时再到其父类和祖先类查找;使用 super 查找匹配方法时,首先到直接父类查找,如果不存在,则继续到其祖先类逐级往高层查找。


     2. final修饰符的使用 

         1.final作为类修饰符: 这种类成为最终类,特点是不允许继承.例如Api中的Math,String,Integer类都是final类. 

         2.final修饰方法: 是功能和内部语句不能被更改的最终方法,在子类中不能再对父类的final方法重定义.所有private修饰的为私有方法和final类中的方法都默认为是final. 

         3.final定义常量:只能被赋值一次 例如 final double PI=3.14159; 

           //注意带static的类常量只能在定义或静态代码块中赋值 

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


     3. 抽象类和抽象方法 

         1.抽象类的定义:抽象类代表了一种优化了的概念组织方式,来描述事物的一般状态和行为,然后在子类中去实现这些状态和行为,以适应对象的多样性. 

         abstract class 类名称{ 

              成员变量;  

              方法(){……}       //一般方法,可存在,可也不存在 

              abstract 方法();  //抽象方法            

         } 

    说明:抽象类中可以包含具体方法和抽象方法,抽象方法的定义与具体方法不同,抽象方法在后直接跟分号,而具体方法都含有方法体. 

          //普通类加上abstract关键字就变成了抽象类,没有任何条件限制.但是有抽象方法的类必须定义为抽象类,否则会提示"The type XXX must be an abstract class to define abstract methods" 

         2. 抽象方法表示一个抽象的概念,不能被实例化为对象. 

       3.抽象类中是有默认的构造函数.我的理解是不过隐藏了不能直接建立对象罢了.当然自己也可以写自己的构造函数.  抽象类中的构造方法供子类实例化调用。 

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

        private  私有内容子类继承不到,所以,不能重写。
                           但是,abstract修饰的方法,要求被重写。两者冲突。
               final
                           final修饰的方法不能被重写。
                           而abstract修饰的方法,要求被重写。两者冲突。                        
               static
                            假如一个抽象方法能通过static修饰,那么这个方法,就可以直接通过类名调用。
                            而抽象方法是没有方法体的,这样的调用无意义。所以,不能用static修饰。 

    牵扯到的模版方法设计模式 

      在定义功能时,功能的一部分是确定的,但是有一部分是不确定的.就将不确定的部分暴露出去,有该类的子类去完成. 


     4. 接口  

         Java中不支持多继承,而是通过接口实现比多重继承更强的功能,java通过接口可以使出于不同层次,甚至不相关的类具有相同的行为.可认为是一种特殊的抽象类. 

          1.接口的定义:由常量和抽象方法组成  

              [public] interface 接口名 [extends 父接口名列表 ]  {   

                  [public] [static] [final] 域类型 域名 = 常量值 ;   

                  [public] [abstract] 返回值 方法名(参数列表) [throw 异常列表];  

              }      

                   [1]声明接口可给出访问控制符;   

                   [2]一个接口还可以继承多个父接口,父接口间用逗号分隔。   

                   [3]系统默认接口中所有属性的修饰都是public static final,毕老师说的全局常量.   

                   [4]系统默认接口中所有方法的修饰都是public abstract;即抽象方法.  

         接口是抽象类的一种,不能用于直接创建对象.接口的作用在于规定一些功能框架,具体功能的实现则通过该接口约束的类完成.     

      2.接口的实现 

             接口定义了一套行为规范,一个类实现这个接口就是要遵守接口的定义规范,要实现接口中定义的所有方法. 

             一个类可以实现多个接口。接口间用逗号分隔;  

             如果实现某接口的类不是抽象类,则在类的定义部分必须实现指定接口的所有抽象方法;否则编译时会指示该类只能为抽象类是不能创建对象的.   

             接口的抽象方法的访问限制符默认为 public,在实现时要在方法头中显式地加上public修饰。  


    5. 多态性(体现在父类或者接口的引用指向或者接收自己的子类对象) 

      作用:
      多态的存在提高了程序的扩展性和后期可维护性.但弊端是父类的引用只能访问父类中的成员.
      前提:
        • 需要存在继承或者实现关系
        • 要有覆盖操作

          1.方法的重载

              方法调用的匹配处理原则是,首先按“精确匹配”原则去查找匹配方法,如果找不到,则按“自动类型转换匹配”原则去查找能匹配的方法。

              所谓“精确匹配”就是实参和形参类型完全一致。

              所谓“自动转换匹配”是指虽然实参和形参类型不同,但能将实参的数据按自动转换原则赋值给形参。     

         2.方法的覆盖

               方法名、参数列表、完全相同才会产生方法覆盖;返回类型通常也要一致,只有返回类型为引用类型时,允许子类方法的返回类型是父类方法返回类型的子类型。其他情形导致类型不一致时编译将指示错误。

              覆盖不能改变方法的静态与非静态属性。子类中不能将父类非静态方法定义为静态方法,反之也一样。 

              不允许子类方法的访问修饰符比父类有更多的限制。例如:子类不能将父类的public方法定义为protected方法。但可以将父类的private方法在子类中重新定义为public方法.通常将子类方法访问修饰符与父类保持一致.

              final方法不能被覆盖。

              [注意] 如果子类中定义了与父类同名的属性,在子类中将隐藏来自父类的同名属性变量. 对象执行方法时由实际对象的类型决定,而不是引用变量类型 ;

            访问属性时则由引用类型决定,因为编译程序在分析程序时是基于类型来决定访问哪个属性变量 ;

            静态成员的访问是基于引用类型,而不是对象类型.

         3.访问继承的成员

              得知通过子类对象赋值给父类的引用变量后,通过该引用变量去访问对象的成员时,访问的行为方法是子类对象的,而属性值确是父类的.其实就是编译系统是基于类型来决定的.

              是基于引用类型/实际对象?

                当子类和父类有相同成员时,通过子类引用访问的成员都是子类定义的,而通过父类引用变量操作子类对象时,只有实例方法存在覆盖关系(编译时看左边:要查看引用变量所属的类中是否有所调用的成员。在运行看右边:要查看对象所属的类中是否有所调用的成员),而对象属性,静态属性,静态方法均是父类定义的.

         4.几个特殊类

               Object类: 所有Java类的最终祖先,编译系统默认继承Object类,Object类包含了所有Java类的公共属性和方法,下面是四个常用方法.

                   public boolean equals(Object obj) :该方法本意用于两个对象的“深度”比较,也就是比较两对象封装的数据是否相等;而比较运算符“==”在比较两对象变量时,只有当两个对象引用指向同一对象时才为真值。但在Object类中,equals方法是采用“==”运算进行比较;

                   public String toString():该方法返回对象的字符串描述,建议所有子类都重写此方法。

                   public final Class getClass():返回对象的所属类;

                   protected  void  finalize(): 该方法Java垃圾回收程序在删除对象前自动执行。

              Class类

              1.获取Class类型的对象

                   Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。有以下3种方法可以获取Class的对象。

              方法1:调用Object类的getClass()方法。

              方法2:使用Class类的forName()方法。

              方法3:如果T是一个Java类型,那么T.class就代表了与该类型匹配的Class对象。例如,String.class代表字符串类型,int.class代表整数类型。

              2.Class类的常用方法

                   java运行环境中提供了反射机制,这种机制允许程序中动态获取类的信息,以及动态调用对象的方法.            

                   [1] static Class<?> forName(String className):返回给定串名相应的Class对象。

                   [2] T newInstance():创建类的一个实例。

                   [3] String getName():返回Class对象表示的类型(类、接口、数组或基类型)的完整路径名字符串。

                   [4] Method[] getMethods():返回当前Class对象表示的类或接口的所有公有成员方法对象的数组。

    进一步利用Method类提供的invoke方法可实现相应类的成员方法的调用。

         Object invoke(Object obj,Object[ ] args)

              其中,obj代表调用该方法的类实例对象,args代表存放方法参数的对象数组。

                   Method getMethods(String name,Class…parameterType):返回指定方法名和参数类型的方法对象。

                   Field[ ] getFields():返回当前Class对象表示的类或接口的所有可访问的公有域对象的数组。


     6. 对象引用转换 

         对象引用赋值转换: 允许将子类对象赋值给父类引用,父类表示的范围比较广,反之则不行. 

         对象引用强制转换 

              将父类引用赋值给子类变量时要进行强制转换,强制转换在编译时总是认可的,但运行时的情况取决于对象的值.如果父类对象引用指向的就是该子类的一个对象,则转换是成功的.否则会抛出异常. 


    7. 内部类(一个类定义在另一个类里面)

         访问特点: 内嵌类经过编译后产生的字节码文件名为:OuterOne$InnerOne.class 

              1.内部类可以直接访问外部类中的成员,包括私有。

                   之所以可以直接访问外部类的成员,是因为内部类中持有了一个外部类的引用,格式: 外部类名.this

              2.外部类要访问内部类,必须建立内部类的对象。

         内部类可以使用访问控制符public、protected、private修饰 

              静态inner类(只能访问外部内的静态成员,出现了访问局限)       

      内部类定义在成员位置上
        • 可以被private static成员修饰符修饰。
        • 被static修饰的内部类只能访问外部类中的静态成员。    

         内部类在定义在局部时(方法中的内部类):

              内部类可以直接访问外部类中的成员。

              内部类在局部位置上只能访问局部中被final修饰的局部变量。    

         匿名内部类 

              Java允许创建对象的同时定义类的实现,但是未规定类名,视为匿名内部类.

              1.匿名内部类是内部类的简写

              2.定义匿名内部类的前提: 必须是继承一个类或实现接口.


    7. 访问控制修饰符

         1.公共访问控制符public

              [1]作为类的修饰符,将类声明为公共类, 表明它可以被所有的其它类所访问和引用 

              [2]作为类的成员的访问修饰符,表明在其他类中可以无限制地访问该成员。 

              要真正做到类成员可以在任何地方访问,在进行类设计时必须同时满足两点:首先类被定义为public,其次,类的成员被定义为public。

         2.默认访问控制符

              没有给出访问控制符情形,该类只能被同一个包中的类访问和引用,不能被其他包中的类使用.

         3.私有访问控制符private

              用来声明类的私有成员,它提供了最高级的保护.用private修饰的域和方法只能被该类自身访问和修改,不能被任何其他类(包括该类的子类)来获取和引用.

              通常,出于系统设计的安全考虑,将类的成员属性定义为private保护起来,而类的成员方法public对外公开,这是类封装特性的一个体现.

         4.保护访问控制符protected

              用protected修饰的成员可以在三种类中所引用: 

                   该类本身;与它在同一个包中的其它类;在其它包中的该类的子类.

    图7.1

     

    ---------thinking、architecture、code、treasure---------
  • 相关阅读:
    react——axios 和fetch-jsonp
    react——路由跳转、动态路由、get传值
    react——生命周期函数
    设置文字在水平垂直居中-高度自动撑开的块级元素也可以
    react——父子组件通信
    react-todoList
    react中获取输入框中值的两种方式——受控组件和非受控组件
    react中事件的使用
    asp.net core mvc视频A:笔记6-1.应用发布与部署
    asp.net core mvc视频A:笔记5-1.路由规则
  • 原文地址:https://www.cnblogs.com/elaa/p/3984005.html
Copyright © 2011-2022 走看看