一、类的继承
在面向对象中,继承是一个类得到了另一个类中的所有*的属性和方法。
被继承的类:父类
去继承其他类的类:子类(继承了父类的,也可以有自己的属性和方法)
特点:
(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类声明对象作为其子类的上转型对象
三、接口