多态及内部类

多态

类的多态

类的多态:

​ 父类引用指向子类对象
​ 父类引用中存储的是子类对象在堆中的地址

需求:老师骑着自行车上班
分析:老师类、自行车类

需求升级/迭代:自行车->小汽车
步骤:

​ 1.创建Car类,编写start、stop
​ 2.在原有Teacher类的基础上编写open、close
​ 注意:违反了OCP原则

OCP - 开闭原则:

​ O - open :在需求升级时,对于创建类是欢迎的

​ C - close:在需求升级时,改变原有代码是拒绝的

注意:需求升级时,尽量不要改变以前的类,否则容易出bug

需求升级/迭代:自行车->小汽车->飞机

步骤:创建Plane类继承Vehicle

	Teacher t = new Teacher();
		
       //类的多态:父类引用指向子类对象
       //父类引用中存储的是子类对象在堆中的地址
       Vehicle v = new Plane();

       t.open(v);
       System.out.println("欣赏沿途的风景...");
       t.close(v);

接口的多态

接口的多态:

​ 实现类的对象指向接口的引用
​ 接口的引用中存放的是实现类对象在堆中开辟空间的地址

public static void main(String[] args) {
		//需求:鼠标、键盘连接电脑
		
		Computer computer = new Computer();
		
		//接口的多态:实现类的对象指向接口的引用
		//接口的引用中存放的是实现类对象在堆中开辟空间的地址
		IUSB usb = new Keyboard();
		
		computer.connection(usb);
	}
//电脑类
public class Computer {

	//连接usb的方法
	public void connection(IUSB usb){
		usb.use();
	}
}
//USB接口类
public interface IUSB {
	
	public void use();

}
//键盘类
public class Keyboard implements IUSB{

	@Override
	public void use() {
		System.out.println("键盘:输入数据~~~");
	}
}

对象转型

向上转型

  1. 向上转型:子类类型 转 父类类型
    1. 可以调用父类非私有的属性
    2. 可以调用父类非私有的方法
    3. 可以调用子类重写父类的方法
    4. 不可以调用子类自身的属性和方法
  2. 注意:向上转型就是多态
  3. 多态的缺点:不可以调用子类自己的属性和方法
public class Test01 {
	
	public static void main(String[] args) {
		A a = new B();
		
		System.out.println(a.aAtrr);//父类属性
		a.aMethod();//父类方法
		a.method();//子类重写父类的方法
	}
}
//父类
public class A {
	String aAtrr = "父类属性";
	
	public void aMethod(){
		System.out.println("父类方法");
	}
	
	public void method(){
		System.out.println("父类方法");
	}
}
//子类
public class B extends A{

	String bAtrr = "子类属性";

	public void bMethod(){
		System.out.println("子类方法");
	}
	
	@Override
	public void method(){
		System.out.println("子类重写父类的方法");
	}
}

向下转型

  1. 向下转型:父类类型 转 子类类型
  2. 注意:
    1. 向下转型转不正确就会出现 - ClassCastException (类型转换异常)
    2. 向下转型一定要使用 instanceof 判断
public static void main(String[] args) {
	Animal an = new Dog();//向上转型

    if(an instanceof Cat){//判断an引用指向的对象是否是Cat类型
        Cat cat = (Cat) an;//向下转型
        cat.shout();
    }else if(an instanceof Dog){//判断an引用指向的对象是否是Dog类型
        Dog dog = (Dog) an;//向下转型
        dog.eat();
    }
}

//Animal类
public class Animal {
}

//Cat类
public class Cat extends Animal{

	public void shout(){
		System.out.println("喵喵喵~~~");
	}
}

//Dog类
public class Dog extends Animal{

	public void eat(){
		System.out.println("啃骨头~~~");
	}
}

内部类

含义:在一个类中声明的类

分类:

  1. 成员内部类 :在成员变量位置处声明的类

    特点:可以调用外部类的所有属性

  2. 静态内部类

    特点:只能调用外部类的静态属性

  3. 接口内部类:在接口中定义的类

    特点:接口内部类底层就是静态内部类

  4. 局部内部类:在方法中定义的类

    注意:该类不能用修饰符修饰

  5. 匿名内部类:

    分为匿名子类和匿名实现类

成员内部类

特点:可以调用外部类的所有属性

public static void main(String[] args){
       //创建成员内部类对象
       Inner inner = new Outter().new Inner();
       //调用方法
       inner.method();
}

//外部类
public class Outter {

	private 	String str1 = "aaa";
				String str2 = "bbb";
	protected 	String str3 = "ccc";
	public 		String str4 = "ddd";
	final 		String str5 = "eee";
	static 		String str6 = "fff";

	//成员内部类
	class Inner{
		private String str1 = "成员内部类的属性~~~";

		public void method(){
			System.out.println("成员内部类里的方法");
			System.out.println(this.str1);//成员内部类里的属性
			System.out.println(Outter.this.str1);//aaa:调用外部类的属性
			System.out.println(str2);//Outter.this.str2
			System.out.println(str3);//Outter.this.str3
			System.out.println(str4);//Outter.this.str4
			System.out.println(str5);//Outter.this.str5
			System.out.println(str6);//Outter.str6
		}
	}
}

静态内部类

特点:只能调用外部类的静态属性

public static void main(String[] args){ 
    //创建静态内部类对象(不用创建外部类对象)
       Inner inner = new Outter.Inner();

       //调用方法
       inner.method();
}

//外部类
public class Outter {
	
       private 	String str1 = "aaa";
       			String str2 = "bbb";
       protected 	String str3 = "ccc";
       public 		String str4 = "ddd";
       final 		String str5 = "eee";
       static 		String str6 = "fff";
	
    //静态内部类
       static class Inner{
   
		        public void method(){
               System.out.println("静态内部类里的方法");
               //静态内部类不能调用外部类的成员变量
               //		System.out.println(str1);
               //		System.out.println(str2);
               //		System.out.println(str3);
               //		System.out.println(str4);
               //		System.out.println(str5);
               System.out.println(str6);//Outter.str6
           }
       }
   }

接口内部类

特点: 接口内部类底层就是静态内部类

public static void main(String[] args) {
		
       //创建接口内部类对象
       Inner inner = new Outter.Inner();

       //调用方法
       inner.method();
}

//接口
public interface Outter {
	
	//接口内部类 默认添加public static
	class Inner{
		public void method(){
			System.out.println("接口内部类里的方法");
		}
	}
}

局部内部类

特点:该类不能用修饰符修饰

public class Test01 {
	
	public static void main(String[] args) {
		//创建外部类的对象
		Outter outter = new Outter();
		
		//调用方法
		Object obj = outter.function();
		System.out.println(obj);
	}
}
//外部类
public class Outter {
	
	public Object function(){
		//如果局部内部类中使用到该变量,从JDK1.8开始该变量自动变成常量(常量在整个项目结束后才被回收)
		//因为防止i在该方法结束后才使用(若i不为常量,方法结束后,变量被回收,若局部内部类访问则报错)
		int i = 100;
		
		//局部内部类
		class Inner{
			@Override
			public String toString() {
				return i+"";
			}
		}
		
		//局部内部类
		class Inner{
			public void method(){
				System.out.println("局部内部类里的方法");
			}
		}
		
		//创建局部内部类的对象
		Inner inner = new Inner();
		inner.method();
		
		return inner;
	}
}

匿名内部类

匿名子类:

  1. 创建匿名子类,继承A,重写method方法

  2. 创建匿名子类对象,赋值给父类的引用

    A a = new A() {
    			@Override
    			public void method() {
    			}
    		};
    

匿名实现类:

  1. 创建匿名实现类,实现 I1中的method方法

  2. 创建匿名实现类的对象,赋值给接口的引用

    I1 i1 = new I1() {
    			@Override
    			public void method() {
    			}
    		};
    

内部类的使用场景

应用场景1:

如果一个类的对象只在另外一个类中使用,就可以考虑把该类变成成员内部类或者静态内部类

  1. 如果内部类要用到外部类的所有属性就把该类变成成员内部类
  2. 如果内部类只用到外部类的静态属性就把该类变成静态内部类
应用场景2:

如果一个类的对象只在另外一个类的方法中使用,就可以考虑把该类变成局部内部类,一般不使用这种设计思想

应用场景3:

如果一个类的对象只在接口中使用,就可以考虑把该类变成接口内部类,一般不使用这种设计思想

应用场景4:

抽象类子类的对象或者接口实现类的对象只使用到一次,就可以考虑使用匿名内部类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值