面向对象(下)

面向对象(下)***

继承

概念:
	类的继承是指在现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类或基类,子类会自动拥有父类所有可继承的属性和方法。
语法格式:
	[修饰符] class 子类名 extends 父类名{
        //程序核心代码
    }
注意:
	类的修饰符是可选的,用来指定类的访问权限,可以使用public或者省略不写
   	子类名和父类名都是必选的,并且子类与父类之间要用extends关键字实现继承关系

案例代码

public class Test2 {
	public static void main(String[] args) {
		//4  我们实验一下 狗中有没有吃方法  先创建狗对象  调用吃方法
		Dog  d=new Dog();
		d.eat(); 
        //打印出 Animal eat
		//5  总结狗类作为动物的子类 从父类中继承到了eat() 方法
	}
}
class Animal{
			//1 父类是在子类中把共性抽象出来的  反推回来 父类中的属性和方法 其实也是子类中的属性和方法
			//2 定义一个吃方法  为什么能把吃方法定义在动物类中,因为我考察过吃这个方法 是所有动物的共性,
			// 所以我把吃这个方法添加在父类中 从而继承Animal类的类都会吃
	public  void eat(){
		System.out.println("Animal eat");
	}

}
		// extends  表示两个类之间的继承关系  说明Animal是Dog的父类 ,反之就是Dog是Animal的子类
class  Dog extends  Animal{
	//3 狗是动物的子类 或者说狗是特殊的动物  那狗肯定也是会吃。 所以在这个程序中狗类有没有吃方法
	} 

继承的注意事项

优点:
	1.提高代码的复用性
	2.提高了代码的维护性
	3.类和类之间产生联系(多态前提)

缺点:
	1.侵入性
	2.降低了代码的灵活性
	3.增强了代码的耦合性

应用场景: 
	类和类之间存在共性的内容,可以考虑使用继承来优化代码

注意事项:
	1.类只支持单继承,不允许多重继承,一个类只能有一个直接父类
	2.多个类可以继承同一个父类
	3.可以多层继承(父类继承其他父类)
	4.父类中的私有属性和方法不能被子类直接调用,只能继承,不能使用(子类范围大于父类)

继承中变量的访问特点

查找顺序:
		1.子类局部
		2.子类成员
		3.父类成员

如果子类和父类中出现同名的成员变量,根据就近原则,本方法--->本类--->父类

Super关键词

this 用法   (本类对象的引用)
	this.变量名:
		当本类局部变量和成员变量发生命名冲突时,this.变量名表示成员变量
	this.方法名:
		调用本类的成员方法
	this(参数表):
		调用本类的其他构造方法(参数表区分调用的构造方法),必须放在本类构造方法执行体语句的第一行

super 用法   (父类对象的引用)
	super.变量名:
		调用父类中的成员变量
	super.方法名:
		调用父类中的成员方法
	super(参数表):
		调用父类的构造方法,必须放在构造方法中执行体语句的第一行
            
作用:
	引用: 父类对象
  	在子类中指定调用父类的构造方法

构造方法特点

1 子类的构造方法都会默认访问父类的无参构造方法   //父类无参构造一般是必须的
	子类在初始化的时候有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用

2 通过构造super()访问父类的构造方法完成父类成员的初始化
	  
3 Object类是所有类直接或者间接父类,如果编写的类没有指定父类,那系统会默认继承Object,也就是说Object类的所有能被继承的属性和方法在其他类中都会有一份
    
4 如果一个构造方法中的第一个语句不是this,也不是super,系统会默认添加super()。默认调用父类的无参构造方法

方法重写(OverRide)

方法重写,也叫方法覆盖

定义:
	子类用特殊的方法实现替换掉父类继承给它的一般的方法实现

语法要求:
	1.访问修饰符相同,或更宽泛
	2.(返回值类型  方法名  参数表)不变
	3.不能比父类抛出更多的异常

注意事项:
	重写的注解: @Override
	1.私有的方法不能重写
	2.静态方法不能重写
	3.子类重写父类方法的时候访问权限必须大于等于父类

重写与重载

重载:
	方法名相同,参数表不同

重写(方法覆盖):
	继承体系不同
	子类出现了和父类一样的方法声明(访问修饰符相同,或更宽泛,返回值类型、方法名、参数表不变,不能比父类抛出更多的异常)

多态

定义:
	多态是同一个行为具有多个不同表现形式或形态的能力

前提:
	要有继承/实现关系
	父类引用指向子类对象(Animal a = new Dog();)
	//要有方法重写(不是必须条件,但经常会使用)

多态中成员访问的特点

构造方法:
	与继承类似,子类构造方法通过super()访问父类的构造方法

成员变量:
	编译看父类,运行看父类
成员方法:
	编译看父类,运行看子类 //如果子类中有对父类方法的重写,则运行时运行子类中重写的方法
原因:成员方法有重写,成员变量没有

多态总结

1.对象类型不变
	一个对象从创建好后实际类型不会变化.
2.只能对引用调用其引用类型中声明的方法
    只能调用直接父类或间接父类中属性和方法
3.运行时会根据对象实际类型找子类重写之后的方法
    当子类对象放进父类引用,该引用调用方法,如果子类重写了该方法,就调用子类的
    /*
	例:
	Animal d = new Dog();
	引用类型为Animal
	实际类型为Dog
	即调用时,d.属性/d.方法调用的是直接父类或间接父类中的属性和方法
	若子类中重写方法,则调用的是子类中重写后的方法
	*/

多态优缺点

1.提高代码的复用性
2.屏蔽不同子类的差异

日常生活中,针对父类使用较多(简单理解为每个人都会吃饭,睡觉.但具体在某个人后怎么吃饭是特有的,并不统一)

多态使用场景

1.多态使用在方法参数上
	m(A(类名) a(变量名))  可以用AA的任何子类对象作为参数
	形参可以使父类引用 而实参可以传子类对象
	public class Test {
		public static void main(String[] args) {
			Dog d=new Dog();
			//调用m1方法
			m1(d);
			//我有个猫对象也想调用m1方法
			Cat c=new Cat();
			m1(c); //这样就是有问题的  所以我们可以重载一个方法
			//但是我有一万个动物呢
		}
		public static  void m1(Animal a){
		a.eat() 
		} //这个能接受所有的动物
		public static  void m1(Dog d){ 
		
		}//这个只能接受狗
		public static  void m1(Cat c){
		
        } //这个只能接受猫
	}
	class  Animal{
		public void  eat(){}
	}
	class Dog extends  Animal{
		public void  eat(){
			System.out.println("骨头");
		}
	}
	class Cat extends Animal{
		public void  eat(){
			System.out.println("鱼");
		}
	}
2.多态用在方法的返回值上
    A m(); 调用方法,可以返回AA的某个子类对象
public class Test {
	public static void main(String[] args) {
		Animal a = m1(1); //现在实际返回的是一只猫
		Animal a = m1(3); //现在实际返回的是一只狗
	}
	public static Animal m1(int a){
		if(a==1){ //如果这样写我这方法的返回对象就不一定了
			return new Cat();
		}
		return new Dog();//以一个狗对象作为一个方法的返回值
	/*
		我们说如果开发需求有变动 方法的实现可能会改变,实现的变动对架构影响是最小的
		我改主意要返回一个猫, 你的返回值类型是狗  但是你现在要返回一只猫,你的返回值类型也需要跟着改变
		如果返回值类型如果修改,那就意味着所有调用这个方法的代码都需要进行修改
		所以我们把返回值类型写成父类 Animal也就是返回一个动物对象。
	 */
			}
		}
class  Animal{
	public void  eat(){
	}
}
class Dog extends  Animal{
	public void  eat(){
		System.out.println("骨头");
	}
}
class Cat extends Animal{
	public void  eat(){
		System.out.println("鱼");
	}
}

多态中的转型

1.子类引用赋值给父类引用  可以直接赋值(--->)
2.父类引用赋值给子类引用  必须强制类型转换(--->)
	//虽然编译可以通过,但有风险(参考小数转整数精确度损失情况)
	//在强制类型转换之前,可以用instanceof判断,避免出现异常

注意:
	对象类型必须保持一致
	Animal d = new Dog();
	Animal c = (Cat) d;
	以上情况转换会报错,不遵循对象类型保持一致原则

instanceof 关键词使用:
	public class Test {
		public static void main(String[] args) {
			Animal a=new Dog();
			System.out.println(a instanceof  Dog);
			System.out.println(a instanceof  Cat);
			System.out.println(a instanceof  Animal);
			/*
			  instanceof关键字  可以在每次做强制类型转换之前判断下
			 */
			if(a instanceof  Dog){
				Dog d=(Dog)a;
			}else{
                System.out.println("不是Dog,不能被转换");
            }
		}
	}
	class  Animal{
		public void  eat(){}
		public  void sleep(){
			System.out.println("sleep 8 hours");
		}
	}
	class Dog extends  Animal{
		@Override
		public void sleep() {
			System.out.println("sleep 6 hours");
		}
		public void  shout(){}
	}
	class Cat extends Animal{

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值