5类的继承

一、类的继承

在面向对象中,继承是一个类得到了另一个类中的所有*的属性和方法。

被继承的类:父类
去继承其他类的类:子类(继承了父类的,也可以有自己的属性和方法)

特点:
(1)子类具有父类的所有属性方法
(2)可以重新定义某些属性,并重写某些方法(覆盖);
(3)子类可以追加新的属性和方法。

Java只支持单继承,不允许多继承
c++、Python支持多继承(更灵活,但可能不严谨)

单继承:每个子类只能由一个父类,但一个父类可以由多个子类,不允许子类具有多个父类。
多继承:一个子类可以继承多个父类。

如果Java想“多继承”,则可以使用接口来实现。

若A-B/C/D-E
直接子类:B是A的直接子类
间接子类:E是A的间接子类

直接父类:A是B的直接父类
间接父类:A是E的间接父类

package course4;

public class Person {
	String name;
	int age;
	
	public void eat(){
		System.out.println("吃饭");
	}
	public void introduce(){
		System.out.println("我的名字是" + this.name);
		System.out.println("我的年龄是" + this.age);
	}

}
package course4;

public class Student extends Person {
	//类的继承,使用extends(扩展)关键字,完成了继承Person类中的所有属性和方法
	
	//增加了年级的属性
	int grade;
	
	//增加了学习的方法
	public void study(){
		System.out.println("学习");
		
	}
	

}

package course4;

public class Tseter {
	public static void main(String [] args){
	//创建一个Student类的对象s1
	Student s1 = new Student();
	s1.name = "张三";
	s1.age = 20;
	s1.grade = 3;
	s1.eat();
	s1.introduce();
	s1.study();
	
	Person p1 = new Person();
	}
}

package course4;

public class Teacher extends Person{
	public void teach(){
		System.out.println("教学");
		
	}

}

输出结果:

吃饭
我的名字是张三
我的年龄是20
学习

· 权限修饰符

package course4;

public class Person {
	//protected权限
	//再次了解一下权限修饰符,现在是default权限
	//若改为private,则需要set和get方法才可被用
    private String name; 
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	private int age;
	
	//protected权限,在同一个类中可以调用,在同一个包中的不同类也可以调用
	protected void eat(){
		System.out.println("吃饭");
	}
	public void introduce(){
		System.out.println("我的名字是" + this.name);
		System.out.println("我的年龄是" + this.age);
	}

}

package course4;

public class Tseter {
	public static void main(String [] args){
	//创建一个Student类的对象s1
	Student s1 = new Student();
	s1.setName("张三") ;
	s1.setAge(20);
	s1.grade = 3;
	s1.eat();
	s1.introduce();
	s1.study();
	
	Person p1 = new Person();
	}
}

输出结果:

吃饭
我的名字是张三
我的年龄是20
学习

protected权限,在同一个类中可以调用,在同一个包中的不同类也可以调用;在不同包的类中一般是不能调用的,在不同包的子类中可以调用

package course44;

import course4.Person;

public class Worker extends Person{
	public void work(){
		this.setName("王五");
		this.setAge(69);
		this.introduce();
		//能够继承不同包中父类Person的protected权限的方法eat()
		this.eat();
	}
	public static void main(String [] args){
		//创建的不是Worker类,是Person类
		Person p = new Person();
		p.setName("李四");
		p.setAge(39);
		p.introduce();
		//创建的是Person对象,无法使用只有继承才能用的eat方法
		//p.eat();
		
		//能够继承,而不是直接调用
		Worker w1 = new Worker();
		w1.eat();
	}
}

子类构造方法的特点
(1)在子类的构造方法中必须调用父类的构造方法(无参)
(2)子类通过super(),调用父类的构造方法
(3)若super不是唯一语句,super应该放在方法的第一行

package course4;

public class Person {
	//protected权限
	//再次了解一下权限修饰符,现在是default权限
	//若改为private,则需要set和get方法才可被用
    private String name; 
    private int age;
    
    public Person(){
    	System.out.println("Person的无参数构造方法");
    }
    public Person(String name,int age){
    	this.name = name;
    	this.age = age;
    }
    
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	//protected权限,在同一个类中可以调用,在同一个包中的不同类也可以调用;在不同包的类中一般是不能调用的,在不同包的子类中可以调用
	protected void eat(){
		System.out.println("吃饭");
	}
	public void introduce(){
		System.out.println("我的名字是" + this.name);
		System.out.println("我的年龄是" + this.age);
	}

}

package course44;

import course4.Person;

//在不同的包中,创建一个worker类,继承另一个包中的Person类
//子类和父类不在同一个包中
public class Worker extends Person{
	
	private String workPlace;
	
	//带参数的构造方法需要子类自己去写
	public Worker(String name, int age,String workPlace){
		//super关键字,调用父类的对象
		super(name,age);//通过super调用父类的两个参数的构造方法,实现name和age的初始化
		//通过super调用父类的构造方法的时候,super语句应该放在构造方法的第一行
		this.workPlace = workPlace;
	}
	
	public void work(){
		this.setName("王五");
		this.setAge(69);
		this.introduce();
		//能够继承不同包中父类Person的protected权限的方法eat()
		this.eat();
	}
	//重新改写一下父类的introduce方法,方法的重写
	//override方法重写的要求:方法名、返回类型、参数列表完全相同
	public void introduce(){
		System.out.println("姓名是" + this.getName());
        System.out.println("年龄是" + this.getAge());
        System.out.println("工作地点是:"+ workPlace);
	}
	
	
	public static void main(String [] args){
		//创建的不是Worker类,是Person类
		
		//能够继承,而不是直接调用
		//子类生成对象的时候,会首先调用父类的无参构造方法
		//但是不会自动调用父类的其他形式的构造方法
		Worker w1 = new Worker("王五",45,"北京");
		
		w1.eat();
		//重新改写一下父类的introduce方法,方法的重写
		//override方法重写的要求:方法名、返回类型、参数列表完全相同
		w1.introduce();
	}
}


输出结果:

吃饭
姓名是王五
年龄是45
工作地点是:北京

用super()调用父类的普通方法

package course44;

import course4.Person;

//在不同的包中,创建一个worker类,继承另一个包中的Person类
//子类和父类不在同一个包中
public class Worker extends Person{
	
	private String workPlace;
	
	//带参数的构造方法需要子类自己去写
	public Worker(String name, int age,String workPlace){
		//super关键字,调用父类的对象
		super(name,age);//通过super调用父类的两个参数的构造方法,实现name和age的初始化
		//通过super调用父类的构造方法的时候,super语句应该放在构造方法的第一行
		this.workPlace = workPlace;
	}
	
	public void work(){
		this.setName("王五");
		this.setAge(69);
		this.introduce();
		//能够继承不同包中父类Person的protected权限的方法eat()
		this.eat();
	}
	//重新改写一下父类的introduce方法,方法的重写
	//override方法重写的要求:方法名、返回类型、参数列表完全相同
	public void introduce(){
		//通过super也可以调用父类中的普通方法,super相当于父类的this
		//在调用普通方法中,super不是必须放在第一行了
		super.introduce();
        System.out.println("工作地点是:"+ workPlace);
	}
	
	
	public static void main(String [] args){
		//创建的不是Worker类,是Person类
		
		//能够继承,而不是直接调用
		//子类生成对象的时候,会首先调用父类的无参构造方法
		//但是不会自动调用父类的其他形式的构造方法
		Worker w1 = new Worker("王五",45,"北京");
		
		w1.eat();
		//重新改写一下父类的introduce方法,方法的重写
		//override方法重写的要求:方法名、返回类型、参数列表完全相同
		w1.introduce();
	}
}


· 增加了一个nation

package course4;

public class Person {
	//protected权限
	//再次了解一下权限修饰符,现在是default权限
	//若改为private,则需要set和get方法才可被用
    private String name; 
    private int age;
    public String nation;
    
    public Person(){
    	System.out.println("Person的无参数构造方法");
    }
    public Person(String name,int age){
    	this.name = name;
    	this.age = age;
    }
    
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	//protected权限,在同一个类中可以调用,在同一个包中的不同类也可以调用;在不同包的类中一般是不能调用的,在不同包的子类中可以调用
	protected void eat(){
		System.out.println("吃饭");
	}
	public void introduce(){
		System.out.println("我的名字是" + this.name);
		System.out.println("我的年龄是" + this.age);
	}

}

package course44;

import course4.Person;

//在不同的包中,创建一个worker类,继承另一个包中的Person类
//子类和父类不在同一个包中
public class Worker extends Person{
	
	private String workPlace;
	
	//带参数的构造方法需要子类自己去写
	public Worker(String name, int age,String workPlace){
		//super关键字,调用父类的对象
		super(name,age);//通过super调用父类的两个参数的构造方法,实现name和age的初始化
		//通过super调用父类的构造方法的时候,super语句应该放在构造方法的第一行
		this.workPlace = workPlace;
	}
	
	public void work(){
		this.setName("王五");
		this.setAge(69);
		this.introduce();
		//能够继承不同包中父类Person的protected权限的方法eat()
		this.eat();
	}
	//重新改写一下父类的introduce方法,方法的重写
	//override方法重写的要求:方法名、返回类型、参数列表完全相同
	public void introduce(){
		//通过super也可以调用父类中的普通方法,super相当于父类的this
		//在调用普通方法中,super不是必须放在第一行了
		super.introduce();
		String a = super.nation;//若nation是default不可以,protected可以(因为是子类)
        System.out.println("工作地点是:"+ workPlace);
	}
	
	
	public static void main(String [] args){
		//创建的不是Worker类,是Person类
		
		//能够继承,而不是直接调用
		//子类生成对象的时候,会首先调用父类的无参构造方法
		//但是不会自动调用父类的其他形式的构造方法
		Worker w1 = new Worker("王五",45,"北京");
		
		w1.eat();
		//重新改写一下父类的introduce方法,方法的重写
		//override方法重写的要求:方法名、返回类型、参数列表完全相同
		w1.introduce();
	}
}


方法重载与方法重写的区别
重载:一个类里,方法名相同,参数列表不同
重写:两个类里,父子关系,继承关系,方法名,参数列表完全相同

final关键字
1.修饰类
使用final将类声明为final类。final类不能被继承,即不能有子类。
(一般处于安全性考虑,将一些类声明为final类)
2.修饰方法
(可以被子类使用,但不能修改)
3.修饰属性

package course5;

public class Person {
	
	//属性,变量用final修饰,不能再更改这个属性了。这时这个属性就不是变量了,而是一个常量
	public final String nation = "中国";//当属性被final修饰时,必须先给赋值(常量必须有值,且之后不被改变)
	
	public  String name;
	
	//方法用final修饰保证方法的安全性,不能被任何子类重写
	public final void introduce(){
		// nation = "美国";此句不可执行
	}

}

package course5;

public class Student extends Person {
	
	public static void main(String [] args){
		Student s = new Student();
		s.introduce();
		
	}

}

~~对象的向上转型
子类引用的对象转换为父类类型称为向上转型。
Person p = new Student();
向上转型会失去原对象的一些属性和功能。

package course5;

public class Person {
	
	//属性,变量用final修饰,不能再更改这个属性了。这时这个属性就不是变量了,而是一个常量
	public final String nation = "中国";//当属性被final修饰时,必须先给赋值(常量必须有值,且之后不被改变)
	
	public String name;
	public int age;
	
	//方法用final修饰保证方法的安全性,不能被任何子类重写
	public void introduce(){
		// nation = "美国";此句不可执行
		System.out.println("我是Person");
	}

}

package course5;

public class Student extends Person {
	
	public String grade;
	
	public void introduce(){
		System.out.println("我是student");
	}
	
	public static void main(String[] args){
		
	    //Student向上转型为Person	
		//使用这种形式创建Student()对象
		Person p = new Student();
		p.name = "张三";
		p.age = 20;
		p.introduce();
		//p.grade();此句不可执行
		
	}

}

输出结果:

我是student

向上转型对象的特点:
1.上转型对象不能操作子类新增的成员变量,不能调用子类新增的方法。
2.上转型对象可以访问子类继承或隐藏的成员变量,也可以调用子类继承的方法或子类重写的实例方法。起作用等价于子类对象调用这些方法。

多态:父类的某个方法被子类重写时可以各自产生自己功能的行为

二、抽象类和抽象方法
类是抽象的,对象是具体的。比类更加抽象的,是抽象类。
面向对象的特征:先抽象后具体

抽象方法:只有方法的定义,没有方法体的方法被称为抽象方法
public abstract void fun();
有方法的定义,返回值类型,方法名,参数列表,没有方法体{}。

只有抽象类才可以拥有抽象方法

1.抽象类不能够生成对象,无法实例化;
2.如果一个类中包含有抽象方法,那么这个类称为抽象类
3.只有普通方法也可以定义抽象类

package course5;

//有抽象方法的类必须定义为抽象类
public abstract class Person {
	
	//属性,变量用final修饰,不能再更改这个属性了。这时这个属性就不是变量了,而是一个常量
	public final String nation = "中国";//当属性被final修饰时,必须先给赋值(常量必须有值,且之后不被改变)
	
	public String name;
	public int age;
	
	//将introduce设置为抽象方法,抽象方法必须要在一个抽象类中,普通类中不能有抽象方法
	public abstract void introduce();
		

}

package course5;

public class Student extends Person {
	
	public String grade;
	
	public void introduce(){
		System.out.println("我是student");
	}
	
	public static void main(String[] args){
		
		//抽象类不能够生成对象,无法实例化。可以创建Person的引用,但是不能够执行 new Person()
		//Person absPerson = new Person();此句前半部分可执行,后半部分不可以
		
		
        //Student向上转型为Person	
		//使用这种形式创建Student()对象
		Person p = new Student();
		p.name = "张三";
		p.age = 20;
		p.introduce();
		//p.grade();此句不可执行
		
		//Teacher类向上转型为Person
		//这种方式就实现了面向对象中的“多态”
		//父类的某个方法被子类重写时,可以各自产生自己的功能和行为
		Person t = new Teacher();
		t.introduce();
		
		Person w = new Worker();
		w.introduce();
		
	}

}

抽象类就是来当做父类的

package course5;

//有抽象方法的类必须定义为抽象类
public abstract class Person {
	
	//属性,变量用final修饰,不能再更改这个属性了。这时这个属性就不是变量了,而是一个常量
	public final String nation = "中国";//当属性被final修饰时,必须先给赋值(常量必须有值,且之后不被改变)
	
	public String name;
	public int age;
	
	//将introduce设置为抽象方法,抽象方法必须要在一个抽象类中,普通类中不能有抽象方法
	public abstract void introduce();
		
	//eat()是一个抽象方法,那么在创建Person的子类时,必须要重写父类Person中的抽象方法
	public abstract void eat();

}

package course5;

public class Student extends Person {
	
	public String grade;
	
	public void introduce(){
		System.out.println("我是student");
	}
	
	//重写eat
	public void eat() {
		System.out.println("学生在食堂吃饭");
		
	}
	public static void main(String[] args){
		
		//抽象类不能够生成对象,无法实例化。可以创建Person的引用,但是不能够执行 new Person()
		//Person absPerson = new Person();此句前半部分可执行,后半部分不可以
		
		
        //Student向上转型为Person	
		//使用这种形式创建Student()对象
		Person p = new Student();
		p.name = "张三";
		p.age = 20;
		p.introduce();
		p.eat();
		
		//p.grade();此句不可执行
		
		//Teacher类向上转型为Person
		//这种方式就实现了面向对象中的“多态”
		//父类的某个方法被子类重写时,可以各自产生自己的功能和行为
		Person t = new Teacher();
		t.introduce();
		
		Person w = new Worker();
		w.introduce();
		
	}

	

}

package course5;

public class Worker extends Person{
	public void introduce(){
		System.out.println("我是worker");
	}

	//重写eat
	public void eat() {
		System.out.println("在工地吃饭");
		
	}

}

package course5;

public abstract class Doctor extends Person{
	//如果抽象类的子类也是一个抽象方法,那么就不是必须重写父类中的所有抽象方法
    //可以重写,也可以不重写
	public void eat(){
		System.out.println("在医院吃饭");
	}

}

抽象类是可以有构造方法的
他在生成子类的时候调用父类的构造方法

package course5;

//有抽象方法的类必须定义为抽象类
public abstract class Person {
	
	public Person(){
		System.out.println("person类的无参构造方法");
	}
	
	//属性,变量用final修饰,不能再更改这个属性了。这时这个属性就不是变量了,而是一个常量
	public final String nation = "中国";//当属性被final修饰时,必须先给赋值(常量必须有值,且之后不被改变)
	
	public String name;
	public int age;
	
	//将introduce设置为抽象方法,抽象方法必须要在一个抽象类中,普通类中不能有抽象方法
	public abstract void introduce();
		
	//eat()是一个抽象方法,那么在创建Person的子类时,必须要重写父类Person中的抽象方法
	public abstract void eat();

}

package course5;

public class Student extends Person {
	
	public String grade;
	
	public Student(){
		System.out.println("student的无参构造方法");
	}
	
	public void introduce(){
		System.out.println("我是student");
	}
	
	//重写eat
	public void eat() {
		System.out.println("学生在食堂吃饭");
		
	}
	public static void main(String[] args){
		
		//抽象类不能够生成对象,无法实例化。可以创建Person的引用,但是不能够执行 new Person()
		//Person absPerson = new Person();此句前半部分可执行,后半部分不可以
		
		//生成子类时,会调用父类的构造方法,首先会调用父类的构造方法,然后在调用子类的构造方法
		
        //Student向上转型为Person	
		//使用这种形式创建Student()对象
		Person p = new Student();
		p.name = "张三";
		p.age = 20;
		p.introduce();
		p.eat();
		
		//p.grade();此句不可执行
		
		//Teacher类向上转型为Person
		//这种方式就实现了面向对象中的“多态”
		//父类的某个方法被子类重写时,可以各自产生自己的功能和行为
		Person t = new Teacher();
		t.introduce();
		
		Person w = new Worker();
		w.introduce();
		
	}

	

}

输出结果:

person类的无参构造方法
student的无参构造方法
我是student
学生在食堂吃饭
person类的无参构造方法
我是teacher
person类的无参构造方法
我是worker

面向抽象编程
面向抽象编程,是指当设计一个类时,不让该类面向具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象。

利用多态的思想,使用上转型对象,将abstract类声明对象作为其子类的上转型对象

三、接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力申博的计算机研究生!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值