多态-抽象类-接口

一.多态

1.概念:一个事物在不同时刻体现出来的不同状态

2.多态的三个前提条件(缺一不可)

1)必须有继承关系    2)必须有重写(子类出现了父类一样的方法声明)    3)有父类引用指向子类对象(向上转型):Fu f = new Zi()

3.成员访问特点:

1)成员变量:编译看左边,运行看左边

2)成员方法(非静态的成员方法)编译看左,运行看右;由于存在方法重载,所以最终运行的是子类的成员方法。

3)静态成员方法编译看左,运行看左;静态方法算不上方法重写,静态直接和类有关系

4)构造方法:对象进行初始化,由于是一种继承关系,还是分层初始化

class Fu{
	public int num = 10;
	
	//父类的成员方法
	public void show(){
		System.out.println("非静态父类方法。。。");
	}
	
	//静态方法
	public static void method(){
		System.out.println("静态的父类方法。。。");
	}
}

//子类
class Zi extends Fu{
	int num = 20;
	
	public void show(){
		System.out.println("非静态的子类方法。。。");
	}
	
	public static void method(){
		System.out.println("静态的子类方法。。。");
	}
}

//测试类
public class DuoTaiDemo {
	public static void main(String[] args) {
		//创建父类的对象:多态的形式
		//父类引用指向子类对象:向上转型
		Fu f = new Zi();
		
		//访问成员变量,编译看左,运行看左
		System.out.println(f.num);
		System.out.println("----------");
		//访问非静态成员方法,编译看左,运行看右
		f.show();
		System.out.println("----------");
		//访问静态方法,编译看左,运行看左
		f.method();
	}

}


4.多态的好处

a.提高代码的维护性(由继承保证)
b.提高代码的扩展性(由多态保证)
java的开发原则:低耦合,高内聚
//父类
class Animal{
	public void eat(){
		System.out.println("eat...");
	}
	public void sleep(){
		System.out.println("sleep...");
	}
}

//猫类
class Cat extends Animal{
	public void eat() {
		System.out.println("cat eat fish。。。");
	}
	
	public void sleep() {
		System.out.println("cat sleep。。。");
	}
	/**
	 * 优化改进,将猫吃和睡的方法封装成独立的功能
	 * */
	public static void useCat(Cat c){
		c.eat();
		c.sleep();
	}
}
//写一个动物的工具类
class AnimalTool{
	//将类中无参构造私有化:目的是为了不让外界创建对象!
	private AnimalTool() {
		
	}
	public static void useAnimal(Animal a){
		a.eat();
		a.sleep();
	}
}

//狗类
class Dog extends Animal{
	
	public void eat() {
		//super.eat();
		System.out.println("dog eat。。。");
	}
	
	public void sleep() {
		//super.sleep();
		System.out.println("dog sleep。。。");
	}
	/**
	 * 优化改进,将狗吃和睡的方法封装成独立的功能
	 * */
	public static void useDog(Dog d){
		d.eat();
		d.sleep();
	}
}
public class DuoTaiDemo2 {
	public static void main(String[] args) {
		Cat c1 = new Cat();
		//c1.eat();
		//c1.sleep();
		Cat c2 = new Cat();
		//c2.eat();
		//c2.sleep();
		//Cat.useCat(c1);
		//Cat.useCat(c2);
		
		Dog d1 = new Dog();
		//d1.eat();
		//d1.sleep();
		Dog d2 = new Dog();
		//d2.eat();
		//d2.sleep();
		//Dog.useDog(d1);
		//Dog.useDog(d2);
		
		//先创建AnimalToo类名直接调用方法
		AnimalTool.useAnimal(c1);
		AnimalTool.useAnimal(c2);
		AnimalTool.useAnimal(d1);
		AnimalTool.useAnimal(d2);
	}

}

5.多态的弊端:不能访问子类特有的功能

class Animal3{
	public void show(){
		System.out.println("show Animal3---");
	}
}


//子类
class Cat3 extends Animal3{
	public void show(){
		super.show();   //访问到父类的构造方法
		System.out.println("show Cat3---");
	}
	
	//特有功能
	public void playGame(){
		System.out.println("cat catch mouse---");
	}
}




public class DuotaiDemo3 {
	public static void main(String[] args) {
		Animal3 a = new Cat3();	//向上转型
		a.show();
		//多态弊端,不能访问子类特有功能
		//a.playGame();  //编译出错
		
		//解决办法 :1)创建子类具体对象
		Cat3 c = new Cat3();
		c.playGame();
		
		//2)向下转型:父类的引用强制转换为子类的引用
		Cat3 c1 = (Cat3) a;
		c1.playGame();
		
	}


}

如何解决多态的弊端?
注意:异常:OOM异常:严重:OutOfMemory:内存溢出!
解决方案:1)创建子类的具体对象,去访问自己的特有功能;虽然可以解决多态的弊端,但从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间,耗费内存,会浪费空间;
2)多态的第三个前提条件:父类引用指向子类对象,那么可不可以将子类的引用指向父类的对象呢?
这是可以的:称为向下转型将父类的引用强制转换为子类的引用:前提必须有父类的引用存在,向下转型依赖于向上转型!

二.抽象类

1.概念:每一个动物的吃和睡的功能不一样,不应该把动物类定义为一个具体类,而是给出一个声明(abstract)

当一个类中如果有抽象功能(抽象方法)的时候,那么这个类一定要定义为抽象类!
2.问题:一个抽象类中可以有非抽象方法吗?
一个抽象类中可以有抽象方法,也可以有非抽象的方法(记住!
3 .抽象类的特点:
1)抽象类不能实例化:抽象类不能创建对象
那么一个抽象类如何进行实例化?
过抽象类多态形式:父类的引用指向子类对象,通过子类进行初始化!
2) 抽象类多态: 强制子类必须重写当前抽象的父类中所有的抽象方法,可以提高代码的维护性( 里面的继承关系可以保证!

4.抽象类的子类特点:
1)抽象类的子类是抽象类,那么没有 意义!最终使用的是通过子类进行对象初始化的,如果子类被抽象修饰了,那么也不能创建对象,所以没有意义。
2)抽象类的子类必须是具体的类。
abstract class Animal{
	//抽象方法:没有方法体的方法
	public abstract void eat();
	public abstract void sleep();
	//具体的方法
	public void show(){
		System.out.println("show Animal......");
	}
}

//抽象的子类;没有意义
/*abstract class Cat extends Animal{
	
}*/

//具体的子类,必须重写父类的方法
class Cat extends Animal{
	@Override
	public void eat() {
		System.out.println("cat eat fish!");
		
	}
	@Override
	public void sleep() {
		System.out.println("cat sleep......");
		
	}
	
}

//测试类
public class AbstractDemo {
	public static void main(String[] args) {
		//当前Animal已经被abstract修饰
		//Animal a = new Animal();//Cannot instantiate the type Animal:抽象类不能实例化
		Animal a = new Cat();	//Animal是抽象类--->通过抽象类多态进行实例化
		a.eat();
		a.sleep();
		a.show();
	}

}

注意:abstract不能和哪些关键字同时使用?
1)private    2)final:方法不能被重写     3)static:静态方法算不上方法重写
5.抽象类多态的练习:
分析:具体到抽象
程序员类:Programmer
成员变量:姓名,工号,工资
构造:有参,无参
成员方法:
setXXX()/getXXX(),
work()
经理类:Manager
成员变量:姓名,工号,工资
额外的属性:奖金
构造:有参,无参
成员方法:
setXXX()/getXXX(),
work()
抽取共性内容:独立的类:Employee(抽象类)普通员工和经理做的事情不一样,work();抽象方法
测试类:
Employee类
package day_08_10_23.abstract02;

public abstract class Employee {
	//成员变量,定义为私有,提供对外访问的setXxx和getXxx方法
	private String name;
	private String num;
	private int salary;
	//无参
	public Employee() {	
	}
	//有参
	public Employee(String name, String num, int salary) {
		super();
		this.name = name;
		this.num = num;
		this.salary = salary;
	}
	
	//公共的访问方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public int getSalary() {
		return salary;
	}
	public void setSalary(int salary) {
		this.salary = salary;
	}
	//抽象方法
	public abstract void work();
	//非抽象方法
	public void show(){
		System.out.println("name:"+name+"----"+"num:"+num);
	}	
}
Manager类
package day_08_10_23.abstract02;

public class Manager extends Employee {
	//无参
	public Manager() {	
	}
	//有参
	public Manager(String name, String num, int salary) {
		super(name, num, salary);
	}
	

	//重写抽象类所有的抽象方法
	public void work() {
		System.out.println("manager talk project!");
	}

}
Programmer类
package day_08_10_23.abstract02;

public class Programmer extends Employee {
    //无参
	public Programmer() {	
	}
	
	//有参
	public Programmer(String name, String num, int salary) {
		super(name, num, salary);
	}

	//重写抽象类中的方法
	public void work() {
		System.out.println("programmer knock program!");

	}

}

测试类
package day_08_10_23.abstract02;
//测试类
public class AbstractTest {
	public static void main(String[] args) {
		Employee m = new Manager("luona","18",8000);
		m.work();
		m.show();
		Programmer p =new Programmer("hangeng","23",6000);
		p.work();
		p.show();

	}

}

三.接口
1.概念:接口体现的是一种扩展功能。比如:猫可以跳高(并不是所有的猫都具有调高功能)
接口的表示:interface 接口名{
}
2.问题:接口里面的方法可以是非抽象方法吗?
不可以,只能是抽象方法 public abstract void jump();
3.特点:接口中没有构造方法;不能直接实例化(不能直接创建对象)
4.接口如何实例化:接口的子类实现
1)接口的子实现类是抽象类没有意义,子类不能创建对象,实际开发中用的就是子类对象进行实例化
2)接口的子实现类一定是非抽象类,可以通过子实现类进行实例化

5.接口多态:接口的引用指向子实现类对象

6.接口的子实现类和接口的关系:implements
格式:class 子实现类名 implements 接口名{
    }
子实现类的命名要见名知意:接口名+impl
package day_08_10_23.interface01;

 interface Jump {
	//非抽象方法:接口中不能有非抽象方法
	/*public abstract void jump(){
		System.out.println("cat can jump!");
	}*/
	
	public abstract void jump();
	
	//构造方法:不能有
	/*public jump(){
	}*/
}

/*//子实现类是抽象类:没有意义,不能实例化
abstract class Cat implements Jump{	
}*/

class Cat implements Jump{
	@Override
	public void jump() {
		System.out.println("cat can jump!");		
	}	
}

//测试类
public class InterfaceDemo1 {
	public static void main(String[] args) {
		//Jump j = new Jump();  //接口不能直接实例化
		
		//通过接口多态的形式:接口的引用指向子实现类对象
		Jump j = new Cat();
		j.jump();

	}

}
7.接口成员的特点:
成员变量:只能是常量,存在默认修饰符:public static final(建议自己给出默认修饰符)
构造方法:接口没有构造方法
成员方法:接口中的成员方法默认修饰符:public abstract(建议自己给出默认修饰符)
package day_08_10_23.interface01;

interface Inter{
	//成员变量
	public static final int num1 = 10;
	public static final int num2 = 20;
	
	//抽象方法
	public abstract void show();
	public abstract void function();
}

//定义接口的子实现类:见名知意:接口名+impl
class InterImpl implements Inter{

	@Override
	public void show() {
		System.out.println(num1);
		System.out.println(num2);	
	}

	@Override
	public void function() {
		System.out.println("function InterImpl...");
		
	}
	
}
//测试类
public class InterfaceDemo2 {
	public static void main(String[] args) {
		//创建接口对象:接口多态的形式
		Inter i = new InterImpl();
		//i.num1 = 20; //当前num1变量被final修饰,不能再赋值
		System.out.println(Inter.num1);
		System.out.println(Inter.num2);
		System.out.println("-----------");
		i.show();
		i.function();
	}

}
8.类、接口之间的关系:
类与类的关系:继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承;
类与接口的关系:实现关系:implements,并且一个类在继承另一个类的同时,可以实现多个接口
(class 子实现类名 extends Object implements 接口名1,接口名2.......)
接口与接口的关系:继承关系:extends,可以是单继承,也可以是多继承!

面试题:接口和抽象类的区别?

1.成员的区别:
1)成员变量:
抽象类:成员变量可以是常量,也可以是变量
接口:成员变量只能是一常量:存在默认修饰符:public static final
2)构造方法:
抽象类:可以是有参构造,也可以是无参构造;作用:通过子类进行数据初始化(通过子类创建对象)
接口:没有构造方法
3)成员方法的区别:
抽象类:可以是抽象方法,也可以是非抽象方法
接口:只能是抽象方法:存在默认修饰符:public abstract
2.关系的区别:
1)类与类的关系:继承关系:extends,java中只支持单继承,不支持多继承,但是可以多层继承!
2)类与接口的关系: 实现关系:implements,并且,一个类在继承另一个类的同时,可以实现多个接口
 (class 子实现类名  enxtends Object implements 接口名1,接口名2...)
   3)接口与接口的关系:继承关系:extends,可以支持单继承,也可以多继承!
3.设计理念的区别:
抽象类:体现的是一种“is a”的关系,存在继承关系!(抽象类多态)
  接口:体现的是一种“like a”的关系,接口的一种扩展功能
接口练习1:老师和学生案例,加入抽烟的额外功能
老师teacher:公有成员:姓名,年龄
                       公有方法:上课
                        附加功能:抽烟
 学生student:公有成员:姓名,年龄
                        公有方法:上课
 分析:可以将老师和学生抽出一个抽象类Person,包含公有属性(name、age),公有方法定义为抽象方法(attedClass)

   抽烟的额外功能定义为一个接口.
Person类
package day_08_10_23.interface03;

public abstract class Person {
	private String name;
	private int age;
	
	//无参
	public Person() {
		
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	//有参
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	//抽象功能
	public abstract void attendClass();
	
}

Teacher类
package day_08_10_23.interface03;

public class Teacher extends Person {

	
	public Teacher() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Teacher(String name, int age) {
		super(name, age);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void attendClass() {
		System.out.println("teacher teach!");

	}

}
Student类
package day_08_10_23.interface03;

public class Student extends Person {

	public Student() {
		super();
	
	}

	public Student(String name, int age) {
		super(name, age);
		
	}

	@Override
	public void attendClass() {
		 System.out.println("student get class");

	}

}
Interface接口
package day_08_10_23.interface03;

public interface Smoking {
	public abstract void smok();
}
SmokingImplTeacher类
package day_08_10_23.interface03;

public class SmokingImplTeacher extends Teacher implements Smoking {

	@Override
	public void smok() {
		System.out.println("teacher smoking!");

	}

}
测试类
package day_08_10_23.interface03;

public class InterfaceTest {

	public static void main(String[] args) {
		Student s = new Student();
		s.setName("罗娜");
		s.setAge(20);
		System.out.println(s.getName()+"----"+s.getAge());
		s.attendClass();
		
		System.out.println("---------------");
		//通过有参构造初始化
		s = new Student("李明",21);
		System.out.println(s.getName()+"----"+s.getAge());
		s.attendClass();
		System.out.println("---------------");
		
		SmokingImplTeacher st = new SmokingImplTeacher();
		st.setName("differ");
		st.setAge(23);
		System.out.println(st.getName()+"----"+st.getAge());
		st.attendClass();
		st.smok();
		
		
	}

}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值