• 2、继承、抽象类


    继承

    继承的概述

     *A:继承的概念
        *a:继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系
        *b:在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,
            构建出来的新类被称作子类,现有类被称作父类
      *B:继承关系的子类特点  
        *a:子类会自动拥有父类所有非private修饰的属性和方法
    

    继承的定义格式和使用

     *A:继承的格式
        class 子类 extends 父类 {}
     *B:雇员(Employee)与研发部员工(Developer)案例:
        *cn.itcast.demo01包下:
        *Employee.java:
    		 /*
    		 * 定义员工类Employee
    		 */
    		class Employee {
    			String name; // 定义name属性
    			
    			public void work() {// 定义员工的工作方法
    				System.out.println("尽心尽力地工作");
    			}
    		}
        *Developer.java:
    	    /*
    		 * 定义研发部员工类Developer 继承 员工类Employee
    		 * 继承了父类中所有非private修饰的成员变量
    		 */
    		class Developer extends Employee {
    			// 定义一个打印name的方法
    			public void printName() {
    				System.out.println("name=" + name);
    			}
    		}
        *测试员工类与研发部员工类:
            /*
           		定义测试类
    		*/
    		public class Example01 {
    			public static void main(String[] args) {
    				Developer d = new Developer(); // 创建一个研发部员工类对象
    				d.name = "小明"; // 为该员工类的name属性进行赋值
    				d.printName(); // 调用该员工的printName()方法
    				d.work(); // 调用Developer类继承来的work()方法
    			}
    		}
        *通过子类对象既可以调用自身的非private修饰的成员,也可以调用父类的非private修饰的成员
    

    继承的好处

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

    继承的注意事项

     *A:继承的注意事项 
    	 *a:在Java中,类只支持单继承,不允许多继承,也就是说一个类只能有一个直接父类,例如下面这种情况是不合法的。
    	     class A{} 
    	     class B{}
    	     class C extends A,B{}  // C类不可以同时继承A类和B类
    	  假如支持多继承例如:
             class A{
             	int a=3;
                public void method(){
    
                }
             } 
    	     class B{
    	     	int a=5;
    	     	public void method(){
    
    	     	}
    	     }
    	     class C extends A,B{
                
    	     } 
    	     class Demo{
    	     	public static void main(String[] args){
    	     		C c=new C();
    	     		System.out.println(c.a);//到底是调用A的还是B的成员变量??无法确定
    	     		c.method();//到底是调用A的还是B的成员方法??无法确定
    	     	}	
    	     }
    	     
         *b:多个类可以继承一个父类,例如下面这种情况是允许的(就像你爹可以多个儿子,但是这些儿子都只有一个爹)
    	     class A{}
    	     class B extends A{}
    	     class C extends A{}   // 类B和类C都可以继承类A
             
         *c:在Java中,多层继承是可以的,
            即一个类的父类可以再去继承另外的父类,
            例如C类继承自B类,而B类又可以去继承A类,这时,C类也可称作A类的子类。下面这种情况是允许的。
    	     class A{}
    	     class B extends A{}   // 类B继承类A,类B是类A的子类
    	     class C extends B{}   // 类C继承类B,类C是类B的子类,同时也是类A的子类
         *d:在Java中,子类和父类是一种相对概念,
             也就是说一个类是某个类父类的同时,也可以是另一个类的子类。
             例如上面的这种情况中,B类是A类的子类,同时又是C类的父类。
    

    继承的体系

    *A:继承的体系:

    					                       动物(吃)
    					                          |
    					           	  -------------------------
    					           |                            |
    					        猫科动物(吃,胎生)          爬行动物(吃,卵生)
    					           |                            |
    			 	-------------------------------        -----------------      
    		       |          			       	   |      |                 |
    		猫(吃,抓老鼠,胎生)              虎(吃,领地,胎生) 蛇(吃,冬眠,卵生)  鳄鱼(吃,潜水,卵生)
    


    ​ *a:动物体系是对每个具体事物共性的抽取,子类的共性抽取形成父类
    ​ *b:父类:具有所有子类的共性内容
    ​ 子类:不但有共性还有自身特有的内容
    ​ *c:整个继承体系,越向上越抽象,越向下越具体

    继承后子类父类成员变量的特点

    A:继承后子类父类成员变量的特点
       a:子类的对象调用成员变量的时候,子类自己有,使用子类,子类自己没有调用的父类
    	   class Fu{
    			//Fu中的成员变量。
    			int num = 5;
    		}
    		
    		class Zi extends Fu{
    			//Zi中的成员变量
    			int num2 = 6;
    			//Zi中的成员方法
    			public void show()
    			{
    				//访问父类中的num
    				System.out.println("Fu num="+num);
    				//访问子类中的num2
    				System.out.println("Zi num2="+num2);
    			}
    		}
    		
    		class Demo{
    			public static void main(String[] args) 
    			{
    				Zi z = new Zi(); //创建子类对象
    				z.show(); //调用子类中的show方法
    			}
    		}
       b:当子父类中出现了同名成员变量
     		class Fu{
    			//Fu中的成员变量。
    			int num = 5;
    		}
    		
    		class Zi extends Fu{
                //Zi中的成员变量
                int num = 6;
                void show(){   
                    //子类的局部变量
                    int num=7
    
                    //直接访问,遵循就近查找原则
                    System.out.println(num);//7
    
                    //子父类中出现了同名的成员变量时
                    //在子类中需要访问父类中非私有成员变量时,需要使用super关键字
                    //访问父类中的num
                    System.out.println("Fu num="+super.num);//5
                    			//访问子类中的num2
                    System.out.println("Zi num2="+this.num);//6
                }
            }
    
            class Demo5 {
                public static void main(String[] args) 
                {
                    Zi z = new Zi(); //创建子类对象
                    z.show(); //调用子类中的show方法
                }
            }
    

    继承后子类父类成员方法的特性_子类重写父类方法

    A:继承后子类父类成员方法的特性
      a:子类的对象调用方法的时候,子类自己有,使用子类,子类自己没有调用的父类
        class Fu{
    		public void show(){
    			System.out.println("Fu类中的show方法执行");
    		}
    	}
    	class Zi extends Fu{
    		public void show2(){
    			System.out.println("Zi类中的show2方法执行");
    		}
    	}
    	public  class Test{
    		public static void main(String[] args) {
    			Zi z = new Zi();
    			z.show(); //子类中没有show方法,但是可以找到父类方法去执行
    			z.show2();
    		}
    	}  
     
     b:为什么要有重写?
         class Fu{
         	public void method(){
         		//上千行代码
                //Fu类中的方法最先存在,那么如果项目需求变了,该方法
                //功能不能够满足我们的需求,此时我们也不会去改这个方法
                //因为项目中可能有大量的功能已经使用到该方法,如果随意修改可能使调用该方法的功能出现问题
                //所以使用重写方式基于原有功能提供更强的功能
         	}   
         }
         class Zi extends Fu{
          
         }
     c:子类中出现与父类一模一样的方法时,会出现覆盖操作,也称为override重写、复写或者覆盖
       class Fu{
    		public void show(){
    			System.out.println("Fu show");
    		}
       }
       
       class Zi extends Fu{
    		//子类复写了父类的show方法
    		public void show(){
    			System.out.println("Zi show");
    		}
    	}
       public  class Test{
    		public static void main(String[] args) {
    			Zi z = new Zi();
    			z.show(); //Zi show 子类有直接使用子类
    		}
    	}  
    

    方法覆盖的需求

    A:方法覆盖的需求 
        a:案例:比如手机,当描述一个手机时,它具有发短信,打电话,显示来电号码功能,
        后期由于手机需要在来电显示功能中增加显示姓名和头像,
        这时可以重新定义一个类描述智能手机,并继承原有描述手机的类。
        并在新定义的类中覆盖来电显示功能,在其中增加显示姓名和头像功能
    
        b:分析:我们不改装(破坏)原来的手机,而是再买一个新的智能手机,不但有原有的功能,而且还有特有功能
               例:厂商发布新手机都是基于原有手机的升级,不会拿着原有的手机在卖,新产一款 
          1:分析类的构建:
               手机类
                属性(成员变量):无
                行为(成员方法):
                   发短信
                   打电话
                   来电显示:显示来电号码
              智能手机类:
                属性(成员变量):无
                行为(成员方法):
                  发短信
                  打电话
                  来电显示:显示来电号码,显示姓名和头像
              
              手机类和智能手机类有共性内容:
                  发短信
                  打电话
                  显示来电号码
          
          2:继承关系分析:
            对于发短信和打电话功能,让智能手机直接沿用(继承)手机的就可以
            但是在智能手机中的来电显示不但实现号码,还显示姓名和头像,同样的都是来电显示功能,智能手机的来电显示比手机的功能更加强大,我们考虑使用重写
    

    方法覆盖的手机案例实现

    	//手机类
    	class Phone{
    		public void sendMessage(){
    			System.out.println("发短信");
    		}
    		public void call(){
    			System.out.println("打电话");
    		}
    		public void showNum(){
    			System.out.println("来电显示号码");
    		}
    	}
    
    	//智能手机类
    	class NewPhone extends Phone{
    		//覆盖父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    		//从现实生活角度考虑沿用原有的showNum方法名便于用户更快熟悉和接受,而不是再起个新的名字
    		//用户还需要花费大量时间慢慢接受
    		
    		public void showNum(){
    			//调用父类已经存在的功能使用super
                //如果不加super这是调用子类自身的showNum(),自己调用自己,递归
                //方法不断入栈导致内存溢出
    			super.showNum();
    			//增加自己特有显示姓名和图片功能
    			System.out.println("显示来电姓名");
    			System.out.println("显示头像");
    		}
    	}
    
    	public class Test {
    		public static void main(String[] args) {
    			new NewPhone().showNum();//来电显示  显示来电姓名 显示头像
    		}
    	}
    
    

    方法覆盖的注意事项

    A:方法覆盖的注意事项
    a:权限:子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
    四大权限:public>默认=protected>private

       class Fu{	
    		void show(){
    
    		}
    		public void method(){
    
    		}
        }
        class Zi() extends Fu{
    		public void show(){//编译运行没问题
    
    		}  
    		void method(){//编译错误
    
    	    }     
        }
     b:方法定义:子类方法和要重写的父类的方法:方法的方法名和参数列表都要一样。
       关于方法的返回值:
         如果是基本数据类型,子类的方法和重写的父类的方法返回值类型必须相同
         如果是引用数据类型,子类的方法和重写的父类的方法返回值类型可以相同或者子类方法的返回值类型是父类方法返回值类型的子类
         class Fu{	
    		int show(){
    
    		}
    		public Fu method(){
    
    		}
    		
    		public Fu method2(){
    
    		}
    		
        }
        class Zi() extends Fu{
    		public int show(){//返回值为基本类型的重写
    
    		}  
    		public Fu method(){//子类的方法和重写的父类的方法返回值类型可以相同
    
    	    }     
    	    public Zi method2(){//子类方法的返回值类型是父类方法返回值类型的子类
    
    	    }     
        }
     c:重载与重写对比:
        重载:
    	    权限修饰符(public private 默认):无关
    	    方法名:重载的两个方法的方法名必须相同
    	    形参列表:
    	      形参类型的顺序不同
    	      形参的个数不同
    	      形参的类型不同
    	      三者至少满足一个
    	    返回值类型:
    	      重载与返回值类型无关
    	重写:
    	    权限修饰符(public private 默认): 
    	      子类方法的权限>=父类的方法的权限
    	    方法名: 
    	      子类方法和父类方法必须相同
    	    形参列表: 
    	       子类方法和父类方法的形参列表必须相同
    	    返回值类型:
    	      基本类数据类型:
    	        必须相同
    	      引用数据类型:
    	       子类方法的返回值类型和父类方法的返回值类型相同
    	       或者
    	       子类方法的返回值类型是父类方法的返回值类型的 子类
    
    

    抽象

    抽象类的产生

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

    抽象类的定义格式

     A:抽象方法定义的格式:
       a:public abstract 返回值类型 方法名(参数);
         抽象类定义的格式:
    	 abstract class 类名 {
    		
    	  }
        b:抽象类示例代码:
    	   /*
    		 *  定义类开发工程师类
    		 *    EE开发工程师 :  工作
    		 *    Android开发工程师 : 工作
    		 *    
    		 *    根据共性进行抽取,然后形成一个父类Develop
    		 *    定义方法,工作: 怎么工作,具体干什么呀
    		 *    
    		 *    抽象类,不能实例化对象, 不能new的
    		 *    不能创建对象的原因:  如果真的让你new了, 对象.调用抽象方法,抽象方法没有主体,根本就不能运行
    		 *    抽象类使用: 定义类继承抽象类,将抽象方法进行重写,创建子类的对象
    		 */
    		public abstract class Develop {
    		   //定义方法工作方法,但是怎么工作,说不清楚了,讲不明白
    			//就不说, 方法没有主体的方法,必须使用关键字abstract修饰
    			//抽象的方法,必须存在于抽象的类中,类也必须用abstract修饰
    			public abstract void work();
    		}
    
    

    抽象类的使用方式

    A:抽象类的使用方式
     /*
     *  定义类,JavaEE的开发人员
     *  继承抽象类Develop,重写抽象的方法
     */
    public class JavaEE extends Develop{
    	//重写父类的抽象方法
    	//去掉abstract修饰符,加上方法主体
    	public void work(){
    		System.out.println("JavaEE工程师在开发B/S 软件");
    	
    	}
    }
    /*
     *  定义Android类,继承开发人员类
     *  重写抽象方法
     */
    public class Android extends Develop{
         public void work(){
        	 System.out.println("Android工程师开发手机软件");
         }
    }
    
    /*
     *  测试抽象类
     *    创建他的子类的对象,使用子类的对象调用方法
     */
    public class Test {
    	public static void main(String[] args) {
    		 JavaEE ee = new JavaEE();
    		 ee.work();//"JavaEE工程师在开发B/S 软件"
    		 
    		 Android and = new Android();
    		 and.work();//"Android工程师开发手机软件"
    	}
    }
    
    

    抽象类特点

    1、抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。

    2、抽象类不可以直接创建对象,原因:调用抽象方法没有意义。

    3、只有覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象。否则该子类还是一个抽象类。

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

    总结

    继承

    1.继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类,子类会自动拥有父类所有方法

    2.继承的好处:

    ​ 1)可继承的属性和方法。

    ​ 2)提高了代表的可维护性

    ​ 3)提高了代码的复用性

    ​ 4)让类与类之间产生了继承关系

    3.继承的弊端:

    ​ 1)类与类之间的耦合度过高

    4.继承特点:

    ​ java中类只能够单继承,不能多继承,可以多层继承

    ​ class Yy extends Object {}

    ​ class Fu extends Yy{}

    ​ class Zi extends Fu {}

    ​ 所有的类都直接或者间接的继承了 Object类,Object类称为祖宗类

    5.继承的注意事项:

    ​ 1)使用关键字 extends 让类与类之间 产生继承关系

    ​ 2)父类私有的成员,子类不能继承,因为根本看不到

    ​ 3)不能为了继承某个功能而随意进行继承操作, 必须要符合 is a 的关系

    ​ 苹果 is a 水果

    ​ 男人 is a 人

    ​ 狗 is a 人 , 这种情况就不能继承了

    6.继承中的成员变量关系:

    ​ 不同名的变量:

    ​ 子类直接继承使用

    ​ 同名的变量:

    ​ 默认访问的是子类自己的成员变量, 想访问父类中的同名变量,请使用 super.成员变量;

    7.继承中的成员方法关系:

    ​ 不同名的方法:子类直接继承使用

    ​ 同名的方法:默认访问的是子类自己的成员方法,想访问父类中的同名方法,请使用 super.成员方法();

    8.super:用来表示当前对象中包含的父类对象空间的引用

    ​ 调用父类的成员变量: super.成员变量;

    ​ 调用方法的成员方法: super.成员方法();

    9.方法重写(override):指 在子父类中,出现了方法声明相同的情况,也叫做方法覆盖,方法复写

    10.方法重写的注意事项:

    ​ 1)子类的方法声明要与父类相同

    ​ 2)子类要重写方法的方法,方法的权限修饰符不能比父类的更低

    ​ 3)父类私有的方法,子类不能够进行方法重写

    11.方法重载(overload):指 在同一个类中,多个方法名称相同,它们的参数列表不同(个数不同,数据类型不同)

    抽象

    1.抽象方法: 方法只有声明部分,没有方法体

    2.抽象类: 包含抽象方法的类,一定是抽象类

    ​ 使用 abstract 修饰的类,是抽象类

    3.抽象类的特点:

    ​ 1)抽象类与抽象方法都必须使用 abstract来修饰

    ​ 2)抽象类不能直接创建对象

    ​ 3)抽象类中可以有抽象方法,也可以没有抽象方法

    ​ 4)抽象类的子类

    ​ 5)实现了抽象方法的具体类

    4.抽象类面试题:

    ​ 1)抽象类中是否可以没有抽象方法?如果可以,那么,该类还定义成抽象类有意义吗?为什么?

    ​ 可以没有抽象方法,有意义,不会让其他人直接创建该类对象

  • 相关阅读:
    Codeforces 1325D
    Codeforces 1325C
    Codeforces 1311F
    Codeforces 1311E
    Codeforces 1311D
    Codeforces 1316C
    JVM调试常用命令——jstack命令与线程状态(4)
    JVM调试常用命令——jstack命令与线程状态(3)
    JVM调试常用命令——jstack命令与Java线程栈(2)
    Java中类的比较与排序方法(应用Comparable接口与Comparator接口)
  • 原文地址:https://www.cnblogs.com/yoci/p/10352331.html
Copyright © 2020-2023  润新知