Java基础:面向对象(中)

本文深入探讨面向对象编程的三大核心特性:封装性、继承性和多态性。重点讲解继承性的概念、格式及Java中的规定,并通过实例演示多态性的应用。

继承性

面向对象的特征之二:继承性 why?

一、继承性的好处: ① 减少了代码的冗余,提高了代码的复用性 ② 便于功能的扩展 ③ 为之后多态性的使用,提供了前提
二、继承性的格式:
class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass

2.1体现:一旦子类A继承父类B以后,子类A中就获取了父类B中声明的所有的属性和方法。
特别的,父类中声明为private的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。
只有因为封装性的影响,使得子类不能直接调用父类的结构而已。
2.2 子类继承父类以后,还可以声明自己特有的属性或方法:实现功能的拓展。
子类和父类的关系,不同于子集和集合的关系。
extends:延展、扩展
三、Java中关于继承性的规定:
1.一个类可以被多个子类继承。
2.Java中类的单继承性:一个类只能有一个父类
3.子父类是相对的概念。
4.子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
5.子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法

四、 1. 如果我们没有显式的声明一个类的父类的话,则此类继承于java.lang.Object类
2. 所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类
3. 意味着,所有的java类具有java.lang.Object类声明的功能。

第一层

package com.atguigu.java;

public class Creature {
	
	public void breath(){
		System.out.println("呼吸");
	}
	
}

第二层

package com.atguigu.java;

public class Person extends Creature{
	
	String name;
	private int age;
	
	public Person(){
		
	}
	
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	
	public void eat(){
		System.out.println("吃饭");
		sleep();
	}
	
	private void sleep(){
		System.out.println("睡觉");
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	
}

第三层

package com.atguigu.java;

public class Student extends Person{
	
//	String name;
//	int age;
	String major;
	
	public Student(){
		
	}
	public Student(String name,int age,String major){
		this.name = name;
//		this.age = age;
		setAge(age);
		this.major = major;
	}
//	public void eat(){
//		System.out.println("吃饭");
//	}
//	
//	public void sleep(){
//		System.out.println("睡觉");
//	}
	
	public void study(){
		System.out.println("学习");
	}
	
	public void show(){
		System.out.println("name:" + name + ",age:" + getAge());
	}
	
}

测试

package com.atguigu.java;

public class ExtendsTest {
	public static void main(String[] args) {
		
		Person p1 = new Person();
//		p1.age = 1;
		p1.eat();
		System.out.println("*****************");
		
		Student s1 = new Student();
		s1.eat();
//		s1.sleep();
		s1.name = "Tom";
		s1.setAge(10);
		System.out.println(s1.getAge());
		
		s1.breath();
		
		
		Creature c = new Creature();
		System.out.println(c.toString());
	}
}

方法重写的理解

方法的重写(override / overwrite)

1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作

2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法。

3.重写的规定:
方法的声明: 权限修饰符 返回值类型 方法名(形参列表) throws 异常的类型{
//方法体
}
约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
② 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为private权限的方法
③ 返回值类型:
父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型(具体放到异常处理时候讲)
********************************************************************** 子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。
面试题:区分方法的重载与重写

//最终执行的eat函数的结果为"学生应该多吃有营养的食物"
public class Person {
	
	String name;
	int age;
	

	 void eat(){
		System.out.println("吃饭");
	}

}
//继承Person的Student重写eat
public class Student extends Person{

	int elsething;

	//对父类中的eat()进行了重写
	public void eat(){
		System.out.println("学生应该多吃有营养的食物");
	}
	
}

super关键字

1、this.thing 关键字将在自己的类中寻找thing
------如果自己的类中没有thing 将在父类中寻找thing
2、super.thing 关键字将直接在父类中寻找thing

//super调用属性和方法
public class Person {
	String name = Person ;
	public void test(){
	}
}
//继承Person的Student重写eat
public class Student extends Person{
	String name = Student;
	//对父类中的eat()进行了重写
	public void test1(){
		System.out.println(this.age);//2
		System.out.println(super.age);//1
		//如果要调用父类中的test
		super.test();
		//this.test是调用自己的test
	}
	//方法的重写
		public void test(){
		}
}

super调用构造器

public class Person {
//	String name ;
//	int age;//如果不加private在子类中将可以直接调用
	private String name ;
	private int age;
	
	public Person(String name , int age){
		this.name = name;
		this.age = age;
	}
}	
public class Student extends Person{
	String major;
	public Student(String name,int age,String major){
	//需要用super调用Person里的构造器
		super(name,age);
		this.major = major;
	}
}

可能遇到的问题

public class Person {

	private String name ;
	private int age;
	
	public Person(int age){
		
	}
}	
public class Student extends Person{
	String major;
	public Student(){
		//函数体内有super()去调用Person内的空参构造器
		//将会报错因为Person内没有空参构造器
	}
}

面向对象特征之三:多态性(封装性、继承性)

1、理解多态性,可以理解为一个事物的多种形态

2、何为多态性:
对象的多态性:父类的引用指向子类的对象(或者子类的对象赋给父类的应用)

3、多态的使用:虚拟方法的使用
Person p2 = new Man();
在编译的时候都是Person内的方法(父类内的)
但是执行的时候都是Man内的方法
总结 : 编译看左边,执行看右边

4、多态性的使用前提: ① 要有类的继承关系 ② 子类要用重写

public class Text {
	public static void main(String[] args) {
		//多态性
		//Person 可以 new 一个 Man
		//也称子类对象的多态性
		//左边 父类 对象 = new 子类
		//父类的应用指向子类的对象
		Person p2 = new Man();
		//p2.earnMoney();报错
		//用Person定义的 p2 无法调用 类Man内单独定义的方法
		//有了p2以后就可以调功能,调用出的方法是子类(Many)重写的方法
		//将之称为虚拟方法的应用
		p2.eat();
		//理解:我让秘书去找一个人,如果找一个男人,或者找一个女人我的态度是不一样的
		
		
		//为什么要有多态性
		//多态性用的非常广
	}
}

5、 为什么要有多态性:

public class AnimalTest {
	public static void main(String[] args) {
		AnimalTest test = new AnimalTest();
		//此时可以调用各种Animal:即Dog\Cat
		
		test.function(new Dog());
	}
	public void function(Animal animal){
		animal.eat();
		animal.shout();
	}
	//如果没有多态性:我们只能再造Dog和Cat
//	public void function(Dog dog){
//		dog.eat();
//		dog.shout();
//	}
//	public void function(Cat cat){
//		cat.eat();
//		cat.shout();
//	}
}

class Animal{
	public void eat(){
		System.out.println("动物:进食");
	}
	
	public void shout(){
		System.out.println("动物:叫");
	}
}


class Dog extends Animal{
	public void eat(){
		System.out.println("狗啃骨头");
	}
	public void shout(){
		System.out.println("汪汪汪");
	}
}

class Cat extends Animal{
	public void eat(){
		System.out.println("猫吃鱼");
	}
	public void shout(){
		System.out.println("喵喵喵");
	}
}

需要注意的是 :多态性不适用于属性
因为属性没有重写这么一说

虚拟方法的再理解

在这里插入图片描述

向下转型

多态性

public class multiplytomakeup {
	public static void main(String[] args) {
		Person p1 = new Man();
		//如何使用Man中自己的方法和属性
		Man m1 = (Man)p1;
		m1.isSmoking = true;
		m1.earnMoney();
	}
}

instanceof关键字的使用

public class multiplytomakeup {
	public static void main(String[] args) {
		Person p1 = new Man();
		//如何使用Man中自己的方法和属性
		Man m1 = (Man)p1;
		m1.isSmoking = true;
		m1.earnMoney();
		
		
		//Woman w1 = (Woman)p1;
		//w1.goShopping();//java.lang.ClassCastException: com.atguigu.java.Man cannot be cast to com.atguigu.java.Woman
		//因为 p1 new的时候为 Man 所有不属于Woman的父类
		
		//instanceof 关键字的使用
		//A instanceof B:判断 A 是否是 类 B 的实例 , 如果是返回true ;如果不是,返回false;
		//使用情景:为了防止出现ClassCastException的异常
		if(p1 instanceof Woman){//p1不是Woman 所以返回false
			Woman w1 = (Woman)p1;
			w1.goShopping();
		}
		
		if(p1 instanceof Man){//p1 是 Man 所以返回True
			Man m2 = (Man)p1;
			m2.isSmoking = true;
			m2.earnMoney();
		}
	}
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值