Java第七课. 面向对象特征2

Java第七课. 面向对象特征2

回顾:

1.封装:把细节隐藏,提高安全性
    步骤 1:把属性私有化;  2:提供2个公共的方法设置/获取
        
2.重载:[同一个类中,方法名相同,参数项不同(个数,数据类型,顺序),与返回值无关];

3.构造方法:方法名与类名相同,无返回值类型;(构造方法一定是重载,反之不成立)
	作用: 1. 实例化对象(默认调用无参构造);
	     2. 创建对象的同时给属性直接赋值(调用有参构造)
            
4.this 关键字: 1.构造方法间的相互调用(这种情况下要放第一行);
			  2.指代当前对象;

1. 继承

1.1 继承的意义
也是面向对象特征之一
引入例子:定义学生类  幼儿园,小学生,初中生,大学生会有公共的东西,也有不同的东西

[问题]:太多相同代码
[解决问题]:使用继承.为什么引入继承?刚才的案例分析?定义的幼儿园,小学生,大学生都是学生,他们有共同的属性和方法,如果按照我们刚刚的编码,代码有很多冗余(相同的代码)

可以这么去处理:定义一个学生类Student,如果一个类(BigStudent)是另外一个类(Student),?可以用BigStudent extends Student,就是大学生是学生,所以大学生继承学生类,我们称BigStudent叫做子类(派生类) ,Student是父类(基类)
1.2 extends关键字
基本语法:
    [访问权限修饰符] [修饰符] 子类名 extends 父类名{
        子类体
    }

由于Java是单亲继承体系,因此在描述类与类的继承关系时, extends 关
键字后面只能是一个名字,而不能是一个列表(后续接口继承的情况,
 extends 后面可以是一个列表)
    
• Java中的继承树根节点为 Object;
• 所有Java中的类都直接或间接继承自 Object ;
/**
 * 小学生继承学生类
 * @author Administrator
 * extends:继承
 */
public class SmallStudent extends Student{

}
学生类(父类):
public class Student extends Object{
	private String stuNo;
	private String stuName;
    
	public String getStuNo() {
		return stuNo;
	}
	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	
	/**
	 * 学习的方法
	 */
	public void study() {
		System.out.println(stuName+"在学习中~");
	}
	public Student() {
		// TODO Auto-generated constructor stub
	}
}
大学生类(子类):
public class BigStudent extends Student{
    private  String sex;
	@Override  
	public void study() {
		// 调用父类的study() 
		super.study();
		System.out.println("边泡妞边学习");
	}
	
	public void play() {
		System.out.println("游戏");
	}
}

小学生类(子类):
public class MinniStudent extends Student{
	
}
测试类:
public class TestMiniStudent {
	public static void main(String[] args) 
        
		MinniStudent student=new MinniStudent();
		student.setStuNo("202001");
		student.setStuName("张三");
		BigStudent bigStudent=new BigStudent();
		bigStudent.setStuNo("202001");
		bigStudent.setStuName("李四");
		bigStudent.study();
	}
}

张三在学习中~
李四在学习中~
边泡妞边学习
1.3 继承的特点
[子类能够继承父类的所有的公共的部分(公共的属性和方法),但是构造方法除外];

miniStudent.setStuNo("202001");
miniStudent.setStuName("张三");2个公开的方法其实是从Student类继承而来的;

继承的优点: 减少代码的冗余,方便代码的复用(父类定义后,子类继承父类就可以使用公共部分)
[Java中的类之间只能支持单继承]:BigStudent继承了Student,而Student默认继承了obdanject,这种关系叫做[多层继承];(A继承B,B继承了C,A可能也从C这边继承了一些公共的属性和方法)

在这里插入图片描述

extends 除了继承的含义,还有一个含义: 扩展
子类可以扩展父类,子类也可以包含自己的特有部分;
1.4 方法的重写(覆写)@Override
概念:
发生在继承关系的子类中,在子类中的某一个方法,方法的修饰符,返回值类型,方法名,参数列表和父类的某一个方法完全一样,称为方法的重写;(构造方法不能被重写)

jdk1.5新特性:@Override,会帮我们检查下面的方法是否是重写,如果不是重写,那么就会报错;
定义一个动物类,动物都会吃,狗类(Dog),继承动物类,定义一个羊类,继承动物类,分别重写dog类和sheep类的吃的方法.定义测试类 ,分别测试dog对象和sheep对象,测试其吃的过程;
/**
 * 自定义动物类
 * @author Administrator
 *
 */
public class Animal {
	//定义私密属性
	private String name;

	public String getName() {
		return name;
	}

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

	public void eat() {
		System.out.println(name+"在吃");
	}
}
public class Dog extends Animal{

	/**
	 * 重写父类的吃的方法
	 */
	@Override
	public void eat() {
		System.out.println(getName()+"在吃骨头~");
	}
public class Sheep extends Animal{

	/**
	 * 重写父类的吃的方法
	 */
	@Override
	public void eat() {
		System.out.println(getName()+"在拱小白菜~");
	}
}

测试类:

public class TestAnimal {

	public static void main(String[] args) {
	//	Animal animal=new Animal("动物");
		
		Dog dog=new Dog();
		dog.setName("旺财");
		dog.eat();
		
		Sheep sheep=new Sheep();
		sheep.setName("喜羊羊");
		sheep.eat();

	}

}

旺财在吃骨头~
喜洋洋在拱小白菜~
1.5 构造方法与继承
public class Animal {
	//定义私密属性
	private String name;

	public String getName() {
		return name;
	}

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

	public Animal(String name) {
		//super();//调用父类的无参构造
		this.name = name;
		System.out.println("我是父类的带参构造");
	}
	public Animal() {
		System.out.println("我是父类的无参构造");
	}
	//eat方法
	public void eat() {
		System.out.println(name+"在吃");
	}
}
public class Dog extends Animal{
	/**
	 * 重写父类的吃的方法
	 */
	@Override
	public void eat() {
		System.out.println(getName()+"在吃骨头~");
		super.eat();//super.方法名() 调用父类的普通方法,普通方法中,这个super.方法名() 放在哪个位置都可以
	}
	
	public Dog() {
		//第一行代码
		//super();//调用父类的无参构造 这行代码写或者不写,都会调用父类的无参构造
		super("旺财");//显式调用父类中的带参数构造
		System.out.println("我是子类Dog的无参构造");
	}
}
public class Sheep extends Animal{
	/**
	 * 重写父类的吃的方法
	 */
	@Override
	public void eat() {
		System.out.println(getName()+"在拱小白菜~");
	}
	public Sheep() {
		super("喜羊羊");
		System.out.println("我是子类sheep的无参构造");

	}
}
public class TestAnimal {

	public static void main(String[] args) {
	//Animal animal=new Animal("动物");
		
		Dog dog=new Dog();//默认调用子类的无参构造
		dog.setName("旺财");
		dog.eat();
		
		Sheep sheep=new Sheep();
		sheep.setName("喜洋洋");
		sheep.eat();

	}
}

我是父类的带参构造
我是子类Dog的无参构造
旺财在吃骨头~
旺财在吃
我是父类的带参构造
我是子类sheep的无参构造
喜羊羊在拱小白菜~
[重点]:
当创建一个子类对象的时候,默认会调用子类的无参数构造,但是因为存在继承关系,所以实例化子类的对象时,父类的无参构造先执行(那是因为子类的构造方法,包括有参和无参构造里面会有默认的super()存在调用父类的无参构造),然后再执行子类的构造方法;

解决带参数报错:2种方法
1.	子类默认调用父类的无参,那就添加个无参;
2.	在子类中指定调用父类的某个构造方法,就要用到super;
1.4 super关键字
[可以使用super关键字来调用父类的构造方法以及普通方法];
[调用父类构造方法的时候,必须把super放在构造方法中的第一行];

在这里插入图片描述

但是父类的无参构造和有参构造不能同时调用,每个类有且仅有一个构造函数会被实例化;
调用普通方法:

在这里插入图片描述

1.41关于super 与 this 能不能同时使用的问题
答案是不能,因为 superthis 在子类调用构造方法时都必须要放在第一行;我们先来看为什么这种情况下 thissuper 要放在第一行;

[super]:
因为继承的原因,在子类进行初始化的时候,必须要先初始化父类,这就需要调用父类的构造方法,super就起到了调用父类的构造方法的作用,也就是初始化父类的作用;因为在java中不允许调用未初始化的成员;

再说为什么要放在第一行,因为编译器会检测构造函数第一行有没有调用父类构造函数(包括有参和无参),如果没有会默认添加 super(),有则不会;如果再第二行调用 super,会对父类进行两次初始化,会造成资源的浪费;而且每个类有且仅有一个构造函数会被实例化;

[this]:
this 的作用就是调用本类的其它构造函数,上面说过每个构造函数会有默认的 super(),或者自定义了带参的 super,这样就已经初始化父类了,所以写了 this 就不能写 super,上面也说了不能出现两个 super;至于要放第一行的原因和 super 差不多;

2. 总结

• 类的继承由关键字 extends 确定,Java语言为单亲继承,及一个子类只能有一个父类,而一个父类可以有多个子类;
• 子类可以重写父类中某一个方法,称为方法覆盖,也称方法重写,是继承中非常重要的知识点。如果子类需要修改从父类继承到的方法的方法体,就可以使用方法覆盖;
• 当构建子类对象时会优先隐式自动调用父类的无参构造方法,而且这个构建调用过程是从父类“向外”递归扩散的,也就是从父类开始向子类一级一级地完成构建,即如果C继承自B,而B继承自A,那么构建C的对象时,会先调用A的构造方法,然后调用B的构造方法,最后调用C的构造方法,以此类推;
• 如果没有无参的父类构造方法,子类必须要使用 super 显示的调用父类的构造方法,而且必须是在子类构造器中做的第一件事;this 引用对象自身、调用自己的构造方法,而 super 调用父类定义的成员变量、方法或构造方法, super 不能当作引用传递给其他的调用者而 this 可以;
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值