继承和多态
继承
特点
1.子类继承了父类的属性,但是私有的方法和属性不能直接调用
2.在子类中可以进行对父类方法的重载和重写
构造方法的作用:①创建对象;②对象的初始化
代码展示
父类Students类
注意:因为类以外的其他类无法直接获取该类的private的属性,所以有了setName和getName方法让外界获取
public class Students {
private String name;
//创建一个无参构造方法
public Students(){
// System.out.println(); //写了this()方法之后,若写了这句在前就报错了
// 构造方法相互调用 this(实参) 必须放在该方法体的第一行
// this("lds");
}
//创建一个有参构造方法
public Students(String name){
//this 关键字表示的是类的对象
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
/**
* 方法的重载和重写(一般用于继承的关系)
* 重载:返回值、方法名要一样 形参 形参个数或者顺序 其中一个不一样就是方法重载
* 重写:返回值、方法名、形参、形参个数 全都要一致 且访问修饰符要大于或者等于父类的
*/
//父类定义的方法
public void study(){
System.out.println(name);
}
}
子类UNStudents类
//子类会继承父类的属性和方法,但是私有的方法和属性不能直接调用
public class UNStudents extends Students{
public UNStudents(){}
//子类特有的方法
public void printName(){
System.out.println("名字:"+getName());
}
//重载了父类的study()方法
public void study(String s){
System.out.println(s+"在学习");
}
//重写了父类的study()方法
public void study(){
/**
* 保存父类的方法 关键字super 表示当前类的父类对象
*/
// super.study();
System.out.println("我在睡觉");
}
}
Test测试类
/**
* 创建对象: 类名 对象名 = new 构造方法
* 自动转型(向上转型) 父类 对象名 = new 子类构造方法
*/
UNStudents unStudents = new UNStudents();
/*子类继承了父类的属性和方法,但是私有的方法和属性不能直接调用*/
unstudents.setName("lds");
unstudents.getName();
方法重载和方法重写
先写结论:
重载: 返回值、方法名要一样 形参 形参个数或者顺序 其中一个不一样就是方法重载
重写: 返回值、方法名、形参、形参个数 全都要一致 且访问修饰符要大于或者等于父类的
Person
父类
public class Person{
void study(){
System.out.println("这是父类的study()方法");
}
}
Student
子类
public class Student extends Person{
//方法1
public void study(String name){
System.out.println(name);
}
/**
* public String study(String name){
* return name;
* }
*
* 此方法编译错误,和方法1比较,可以得出结论为单纯的返回值不同,方法的其他东西都相同构成不了方法重载
*
* protected void study(String name){
* System.out.println(name);
* }
*
* 此方法编译错误,和方法1比较,可以得出结论为单纯的修饰符不同,方法的其他东西都相同构成不了方法重载
*
* protected String study(String name){
* System.out.println(name);
* return name;
* }
* 此方法编译错误,和方法1比较,可以得出结论为返回值和修饰符不同,方法的其他东西都相同构成不了方法重载
*
*/
//方法2
public void study(String name,int age) {
System.out.println(name+"今年"+age+"岁");
}
//方法3
public void study(int age,String name){
System.out.println(name+"今年"+age+"岁");
}
}
Student
子类
//修饰符:public > protected > 默认 > private
protected void study(){
System.out.println("我爱玩");
}
//方法2
/**
* int study(){
* System.out.println("我爱玩");
* }
*
* private void study(){
* System.out.println("我爱玩");
* }
*
* 上面两个方法编译报错,即方法重写需要返回值要相同,且修饰符需要等于或者大于父类的修饰符才行。
且idea比较只能如果是重写方法左边会有个小标志出来的。也可由此来判断是否是方法重写
*/
说到了继承就不能不提多态
多态
所谓多态,就是一个事务展现出不同的形态,拿水果来说,水果展现出不同的形态,如桃子西瓜等等,桃子和西瓜都是水果,但是水果不能只是桃子或者西瓜。桃子或者西瓜只是水果的一种形态。同理,Java中的多态也是这个道理和思路。
特点
1.多态的作用是降低代码的耦合度,提高代码的复用性
2.多态的三个基本条件:要有继承;父类引用指向子类对象;子类重写和重载父类方法(如果没有也是多态,但是没有意义)
3.多态中除了重写方法是调用子类的,其他的所有的东西都是调用父类的
代码展示
Students类
public class Students{
public int a = 10;
public void study(){
System.out.println("父类的study方法");
}
}
UNStudents类
public class UNStudents extends Students{
public int a = 20;
public void study(){
System.out.println("子类的study方法");
}
}
Test类
//符合多态前两个条件
Students students =new UNStudents();
/**
* 多态中除了重写方法是调用子类的,其他的所有的东西都是调用父类的
*/
System.out.println(students.a); //这里输出的是父类的a = 10
students.setName("lds");
students.study();//这里输出的是子类的方法里的内容(如果需要输出父类的内容,需要在子类的重写方法中用super()方法)
模拟一个场景
饲养员 饲养 动物园里的动物
普通的方法可以行驶,但是假如很多动物,有狗和猪等等,代码就很冗余
Cat类
Class Cat extends Animals{
public void eat(){
System.out.println("猫吃鱼");
}
}
Feeder类
public class Feeder{
public void feed(Cat c){
c.eat();
}
/*假如这里加入狗的引用对象,其他动物假如的话会使代码冗余*/
public void feed(Dog d){
d.eat();
}
}
主方法类
此时增加Dog
类,则上面的feeder
类就需要增加一个d.eat()
的方法
public Class main{
public static void main(String[] args){
Cat c = new Cat();
c.eat();
//Feeder类加了feel(Dog g)方法,因此增多了Dog类
Dog g = new Dog();
d.eat();
}
}
改变上面程序,增加一个父类Animals
Class Dog extends Animals{
public void eat(){
System.out.println("狗吃骨头");
}
}
Animals
类
Class Animals{
public void eat(){
System.out.println("动物吃东西");
}
}
改写Feeder
类
public class Feeder{
public void eat(Animals a){
a.eat();
}
}
改写主方法类
public Class main{
public static void main(String[] args){
Feeder feeder = new Feeder();
Animals c = new Cat();
feeder.eat(c);
Animals g = new Dog();
feeder.eat(g);
}
}
但是多态有弊端:父类引用指向子类对象,子类对象只能调用子类重写父类的方法,那用多态如何调用子类中的特有的方法呢?
用向下转型 UNStudents unstudents = (UNStudents) students;
可以解决这个问题;而向上转型就是多态父类引用指向子类对象。
在向下转型中在尝试父类的实例对象转换为他的子类对象类型之前确保该父类对象是另一个该子类对象的实例,可以利用运算符instanceof
来实现。
主方法main()
/*Students类和UNStudents类同上*/
Students students = new UNStudents();
if(students instanceof UNStudents){
UNStudents students1 = (UNStudents) students;
students1.study(); //子类重写父类的study方法
students1.study("lds"); //
}