Loading

多态-抽象类-接口


返回 我的技术栈(Technology Stack)



多态(polymorphic)


  • 多态的前提:

    • 要有继承关系
    • 要有方法重写
    • 要有父类引用指向子类对象
  • 成员变量:编译看左边(父类);运行看左边(父类)

  • 成员方法:编译看左边(父类);运行看右边(子类)----即动态绑定:先看父类是否有该成员方法,通过编译,再执行子类的成员方法

  • 静态方法:编译看左边(父类);运行看左边(父类)

  • 注意:静态和类相关,算不上重写,所以,访问还是左边的。只有非静态的成员方法,编译看左边,运行看右边

     class Test {
     	public static void main(String[] args) {
     		Fu f = new Zi();  //父类引用指向子类对象——向上转型   Zi hai = (Zi)f;——向下转型
     	//f.method();  运行报错!  //成员方法编译看左边,运行看右边。
     					//即先看父类中是否有该方法,通过了再执行子类,若子类没有该方法,就执行父类的方法(因为继承)
     		f.show();
     	}
     }
    
     class Fu {
     	public void show() {
     		System.out.println("fu show");
     	}
     }
    
     class Zi extends Fu {
     	public void show() {
     		System.out.println("zi show");
     	}
    
     	public void method() {
     		System.out.println("zi method");
     	}
     }
    
     运行结果:zi show
    
     上转型:只能执行被子类所重写过的方法和被子类继承的方法
     Animal mydog = new Dog();
     把mydog当成Animal;父类使用子类中的方法。
    

抽象类的概述及特点


  • 抽查类的特点:
    • 抽象类和抽象方法必须用abstract关键字修饰
    • 如:abstract class 类名 {}
    • public abstract void eat ();
  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口。抽象方法在抽象类中,父类中的抽象方法强制子类重写
  • 抽象类不能被实例化
  • 抽象类的子类:
    • 要么是抽象类

    • 要么重写抽象类中的所有抽象方法

      	抽象类的猫狗案例
      	class Test_Animal {
      		public static void main(String[] args) {
      			Cat c = new Cat("加菲",8);
      			System.out.println(c.getName() + "------" + c.getAge());
      			c.eat();
      			c.catchMouse();
      
      			Dog d = new Dog("八公",30);
      			System.out.println(d.getName() + "------" + d.getAge());
      			d.eat();
      			d.lookHome(); 
      		}
      	}
      
      	abstract class Animal {
      		private String name;  //姓名
      		private int age;   //年龄
      		
      		public Animal() {}    //无参构造
      		public Animal(String name,int age) {
      			this.name = name;
      			this.age = age;
      		}
      
      		public void setName(String name) {   //设置姓名
      			this.name = name;
      		}
      		public String getName() {    //获取姓名
      			return name;
      		}
      
      		public void setAge(int age) {   //设置年龄
      			this.age = age;
      		}
      		public int getAge() {    //获取年龄
      			return age;
      		}
      
      		public abstract void eat();   //吃饭的抽象方法
      	} 
      
      	class Cat extends Animal {
      		public Cat() {}   //空参构造
      		public Cat(String name,int age) {  //有参构造
      			super(name,age);
      		}
      
      		public void eat() {     //抽象类中含有抽象方法,子类必须重写该方法
      			System.out.println("猫吃鱼");
      		}
      
      		public void catchMouse() {
      			System.out.println("抓老鼠");
      		}
      	}
      
      	class Dog extends Animal {
      		public Dog() {}    //无参构造
      		public Dog(String name,int age) {  //有参构造
      			super(name,age);
      		}
      
      		public void eat() {  //抽象类中含有抽象方法,子类必须重写该方法
      			System.out.println("狗吃肉");
      		}
      
      		public void lookHome() {
      			System.out.println("看家门");
      		}
      	}
      
      	输出结果:加菲------8
      			 猫吃鱼
      			 抓老鼠
      			 八公------30
      			 狗吃肉
      			 看家门
      
      	/********************************************************/
      
      	抽象类练习员工案例
      	class Test_Employee {
      		public static void main(String[] args) {
      			Coder c = new Coder("德玛西亚","007",8000);
      			c.work();
      
      			Manager m = new Manager("赵老师","9527",3000,20000);
      			m.work();
      		}
      	}
      
      	abstract class Employee {
      		private String name;     //姓名
      		private String id;       //工号
      		private double salary;    //薪水
      
      		public Employee() {}    //无参构造
      		public Employee(String name,String id,double salary) {  //有参构造
      			this.name = name;
      			this.id = id;
      			this.salary = salary;
      		}
      
      		public void setName(String name) {  //设置姓名
      			this.name = name;
      		}
      		public String getName() {  //获取姓名
      			return name;
      		}
      
      		public void setId(String id) {  //设置工号
      			this.id = id;
      		}
      		public String getId() {  //获取工号
      			return id;
      		}
      
      		public void setSalary(double salary) {  //设置薪水
      			this.salary = salary;
      		}
      		public double getSalary() {  //获取薪水
      			return salary;
      		}
      
      		public abstract void work();  //抽象的工作方法
      	}
      
      	//程序员
      	class Coder extends Employee {
      		public Coder() {}   //无参构造
      		public Coder(String name,String id,double salary) {   //有参构造
      			super(name,id,salary);
      		}
      
      		public void work() {
      			System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() + 
      			",我的工资是:" + this.getSalary() + ",我的工作内容是敲代码");
      		}
      	}
      
      	//项目经理
      	class Manager extends Employee {
      		private int bonus;   //奖金				
      
      		public Manager() {}   //无参构造
      		public Manager(String name,String id,double salary,int bonus) {  //有参构造
      			super(name,id,salary);
      			this.bonus = bonus;
      		}
      
      		public void work() {
      			System.out.println("我的姓名是:" + this.getName() + ",我的工号是:" + this.getId() +
      			 ",我的工资是:" + this.getSalary() + ",我的奖金是:" + bonus + ",我的工作内容是管理");
      		}
      	}
      
      	//我的姓名是:德玛西亚,我的工号是:007,我的工资是:8000.0,我的工作内容是敲代码
      	  我的姓名是:赵老师,我的工号是:9527,我的工资是:3000.0,我的奖金是:20000,我的工作内容是管理
      

抽象类中的面试题


          1、一个抽象类如果没有抽象方法,可不可以定义为抽象类?有什么意义?
         答案:可以。这么做的目的只有一个,就是不让其他类创建本类对象,交给子类完成
          2、abstract不能喝哪些关键字共存?
         答案:static  理由:被abstract修饰的方法没有方法体
                             被static修饰的可以用“类名.”调用,但是“类名.”调用抽象方法是没有意义的
               final   理由:被abstract修饰的方法强制子类重写
                             被final修饰的不让子类重写,所以他俩是矛盾的
               private 理由:被abstract修饰的是为了让子类看到并强制重写
                             被private修饰不让子类访问,所以他俩是矛盾的 

接口的概述及其特点


  • 概念:

    • 狭义上就是指Java中的interface
    • 广义上就是对外提供规则的都是接口
    • 例如:
      • //注意接口不能被实例化,在接口中定义的变量,都是常量(类似被final修饰)

      • //接口中没有构造方法;接口中不能定义非抽象方法

         	 interface Inter {
                   public abstract void print();      //接口中的方法是抽象的
             }
             class Demo implements Inter {           //类实现接口用implements
                   public void print() {
                        System.out.println("文本");
                   }
             }
        
  • 接口的子类:

    • 可以是抽象类。但是意义不大。
    • 可以是具体类。要重写接口中的所有抽象方法(推荐方案)
  • 接口的成员特点

    • 成员变量:只能是常量,并且是静态的并非公共的。
      • 比如:

          	class Demo_Interface {
          		public static void main(Strings[] args) {
          			Demo d = new Demo();
          			d.print();
          	
          			System.out.println(Inter.num);  //不报错,匿名调用,说明是静态
          	    }
          	}
        
          	interface Inter {
          		//对上方的解释:隐藏了修饰符 public static
          		int num = 10;   
          	    //对下方的解释:接口的变量中隐藏了final关键字   final int num = 10;变成了最终常量
          		
          		/*总结两者:接口成员变量默认的修饰符:public static final    
          		  建议自己手动给出  public static final int num =10;*/
          		
          		/*public Inter() {}  运行报错! 接口中没有构造方法   
          		  接口相当于干爹,Demo类访问的是object类中的构造方法*/
          		
          		 /*public void print() {} 运行报错! 接口中不能定义非抽象方法  */
          		
                 	public abstract void print(); //成员方法只能是抽象方法    
          									 //默认修饰符:public abstract 建议自己手动给出
          		
          	
          	}
        
          	class Demo implements Inter {   //一个类不写继承任何类,默认继承object类   
          									// 即相当于 class Demo extends object implements Inter{}
        
          		public void print() {
          		//	num = 20; 报错!    //final int num = 10;变成了最终常量,不能被修改
          			System.out.println(num);
          		}
        
          	}
          	
          	运行结果:10
          			 10
        

类与类,类与接口,接口与接口的关系


  • 1、类与类:
    • 继承关系,只能单继承,也可以多层继承——如:class Person extends Teacher
  • 2、类与接口:
    • 实现关系,可以单实现,也可以多实现——如:class Demo implements InterA,InterB {}
    • 并且还可以在继承一个类的同时实现多个接口——如:class Demo extends object implements InterA,InterB {}
  • 3、接口与接口:
    • 继承关系,可以单继承,也可以多继承——如:interface InterC extends InterB,InterA{}

抽象类和接口的关系:


      A:成员区别
             1、抽象类:
                 (1)成员变量:可以变量,也可以常量
                 (2)构造方法:有
                 (3)成员方法:可以抽象,也可以非抽象
             2、接口:
                 (1)成员变量:只可以常量
                 (2)成员方法:只可以抽象
      B:关系区别
             1、类与类:继承,单继承
             2、类与接口:实现,单实现,多实现
             3、接口与接口:继承,单继承,多继承
      C:设计理念区别
             1、抽象类  被继承体现的是:“is a”的关系。抽象类中定义的是该继承体系的共性功能
             2、接口  被实现体现的是:“like a”的关系。接口中定义的是该继承体系的扩展功能

猫狗案例演示


	动物类:姓名,年龄,吃饭,睡觉
	猫和狗
	动物培训接口:跳高

	class Demo_Animal {
		public static void main(String[] args) {
			Cat c = new Cat("加菲",8);
			c.eat();
			c.sleep();

			JumpCat jc= new JumpCat("跳高猫",3);
			jc.eat();
			jc.sleep();
			jc.jump();
		}
	}

	abstract class Animal {
		private String name;  //姓名
		private int age;    //年龄

		public Animal() {}   //无参构造
		public Animal(String name,int age) {   //有参构造
			this.name = name;
			this.age = age;
		}

		public void setName(String name) {  //设置姓名
			this.name = name;
		}
		public String getName() {  //获取姓名
			return name;
		}

		public void setAge(int age) {  // 设置年龄
			this.age = age;
		}
		public int getAge() {  //获取年龄
			return age;
		}

		public abstract void eat();   //吃饭的抽象方法
		public abstract void sleep();  //睡觉的抽象方法
		//抽象方法要在抽象类中!

	}

	interface Jumping {    //跳高的接口
		public abstract void jump();
	}

	class Cat extends Animal {
		public Cat() {}   //无参构造
		public Cat(String name,int age) {   //有参构造
			super(name,age);
		}

		public void eat() {
			System.out.println("猫吃鱼");
		}

		public void sleep() {
			System.out.println("侧着睡");
		}
	}

	class JumpCat extends Cat implements Jumping {
		public JumpCat() {}  //无参构造
		public JumpCat(String name,int age) {   //有参构造
			super(name,age);
		}

		public void jump() {
			System.out.println("猫跳高");
		}
	}

	输出结果:猫吃鱼
			 侧着睡
			 猫吃鱼
			 侧着睡
			 猫跳高

总结:
抽象类:只有普通方法和抽象方法。
接口:只有全局常量和抽象方法。没有普通方法


posted @ 2021-03-27 23:22  言非  阅读(73)  评论(0编辑  收藏  举报