解析java中的继承
1 含义
在符合当代社会的约定俗成的逻辑的情况下,很多类具有相同的属性和方法,我们这些共有的属性和方法抽象成一个类后,通过extends关键字使得很多类与抽象成的类建立父子关系,其中很多类称为子类,抽象出来的类叫做父类。
2 为什么需要继承?
2.1 减少代码的冗余,提高复用性
例如Chinese类和Russian类都有name、sex、age这三个属性,
那么如果每个类都写的话,就是如下所示的代码
Chinese类
public class Chinese{
private String name;
private String sex;
private int age;
public Chinese() {
}
public Chinese(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Russian类
public class Russian {
private String name;
private String sex;
private int age;
public Russian() {
}
public Russian(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
我们不难发现这两个类里面的一些属性其实是公共的,可以抽象成一个People类
改进后的代码如下所示
Chinese类
public class Chinese extends Peple{
}
Russian类
public class Russian extends Peple{
}
People类
public class Peple {
private String name;
private String sex;
private int age;
public Peple() {
}
public Peple(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
我们可以发现此时的Chinese类和Russian类清爽多了,咱们也可以通过set和get方法去写入和读取它
2.2 便于功能的扩展
例如你想对某些类加上一个功能,没学继承之前你可能得这么干
Chinese类
public class Chinese {
private String name;
private String sex;
private int age;
//你想要增加weight体重这个属性,你得在Chinese里面增加weight这个属性
private int weight;
public Chinese() {
}
public Chinese(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你得增加Chinese类中增加和修改体重的方法
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Russian类
public class Russian{
private String name;
private String sex;
private int age;
//你想要增加weight体重这个属性,你得在Russsian里面增加weight这个属性
private int weight;
public Russian() {
}
public Russian(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你得增加Russian类中增加和修改体重的方法
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
你会发现当需要增加一个属性时,你得将每个需要加上的类中加上这个属性以及它的set/get方法,非常的麻烦,当我们使用继承后,改进后的代码如下所示
Chinese类
public class Chinese extends Peple{
}
Russian类
public class Russian extends Peple{
}
People类
public class Peple {
private String name;
private String sex;
private int age;
//你想要增加weight体重这个属性,只需要在Chinese类和Russian类的父类去增加属性即可
private int weight;
public Peple() {
}
public Peple(String name, String sex, int age,int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
这样去增加和修改共有的属性是很方便的
2.3 为多态性的使用,提供了前提
3 如何使用继承
3.1 判断两个类之间是否存在继承关系的方法
a.判断两个类是否存在逻辑层面上面的父子关系
例如Dog类和People类,显然两者之间不存在逻辑层面的上的父子关系,人不可能是狗的亲生父亲,狗也不可能是人的亲生父亲。
b.公式法: A类 is B类或者B类 is A类是否成立,其中后者为父类,前者为子类
例如Dog类和People类,既不满足Dog is People,也不满足People is Dog 而Animal类和Dog类,满足Dog is Animal,因此Animal类和Dog类存在继承关系,其中Animal是父类,Dog是子类
3.2 语法
class A extends B{
//其中A类为子类,派生类
//B类为父类,超类,基类
}
3.3 规则
3.3.1 子类继承父类,调用构造方法时,一定会需要先调上父类的其中的任意一个构造方法,再调用自己的构造方法,若子类构造方法里面没有调用父类的,那么就会报错。注意:子类无参会默认调用父类无参构造的(默认会使用super()😉)
错误示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
private void print(int count){
System.out.println("父类中的私有化方法"+count);
}
public void show(int count){
print(count);
}
}
Test02类
public class Test03 {
public static void main(String[] args) {
Chinese c=new Chinese();
}
}
错误示例代码运行截图
正确示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
System.out.println("调用Chinese类里面的无参构造方法");
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public Peple() {
System.out.println("调用People类的无参构造方法");
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Test03类(测试类)
public class Test03 {
public static void main(String[] args) {
Chinese c=new Chinese();
}
}
正确示例代码运行截图
3.3.2 一个类只能继承于一个父类,但一个父类可以被多个子类继承.(单继承)
错误示例代码(一个类继承了多个父类)
Chinese类
public class Chinese extends Peple,Creature{
public Chinese() {
//实际上是在首行省略了super();
System.out.println("调用Chinese类里面的无参构造方法");
}
}
错误示例代码在编译器里面的错误提示
正确示例代码(1个父类可以有多个子类,一个子类仅有一个父类)
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
System.out.println("调用Chinese类里面的无参构造方法");
}
}
Russian类
public class Russian extends Peple{
public Russian() {
System.out.println("调用Russian类里面的无参构造方法");
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public Peple() {
System.out.println("调用People类的无参构造方法");
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Chinese c=new Chinese();
System.out.println("-------------------");
Russian russian=new Russian();
}
}
正确示例代码运行截图
3.3.3 子类继承父类时,会将所有属性和方法,都复制到自己的空间,这是一个副本,对子类进行数据的修改时,不会对父类的数据造成影响
a 公开属性
示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
}
}
People类
public class Peple {
public String name;
private String sex;
private int age;
private int weight;
public Peple() {
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Peple p=new Peple();
Chinese c=new Chinese();
//只需要子类修改了继承过来的属性和方法,看是否对父亲原来的属性和方法造成影响
c.name="张三";
p.name="李四";
System.out.println("子类中,名字为:"+c.name);
System.out.println("父类中,名字为:"+p.name);
// System.out.println("-------------------");
// Russian russian=new Russian();
}
}
示例代码运行截图
b 公开方法
示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public int count;
public Peple() {
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public void test(int count){
this.count=count;
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Peple p=new Peple();
Chinese c=new Chinese();
//只需要子类修改了继承过来的属性和方法,看是否对父亲原来的属性和方法造成影响
System.out.println("调用父类公开方法时");
p.test(6);
System.out.println("调用子类公开方法时");
c.test(2);
System.out.println("子类中,count的值为:"+c.count);
System.out.println("父类中,count的值为:"+p.count);
// System.out.println("-------------------");
// Russian russian=new Russian();
}
}
示例代码运行截图
c 私有属性
示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public Peple() {
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Peple p=new Peple();
Chinese c=new Chinese();
//只需要子类修改了继承过来的属性和方法,看是否对父亲原来的属性和方法造成影响
System.out.println("使用父类对象进行更改名字属性时");
p.setName("张三");
System.out.println("使用子类对象进行更改名字属性时");
c.setName("王五");
System.out.println("父类中,name属性值为: "+p.getName());
System.out.println("子类中,name属性值为:"+c.getName());
}
}
示例代码运行截图
d 私有方法
示例代码
Chinese类
public class Chinese extends Peple{
public Chinese() {
//实际上是在首行省略了super();
}
}
People类
public class Peple {
private String name;
private String sex;
private int age;
private int weight;
public Peple() {
}
public Peple(String name, String sex, int age, int weight) {
this.name = name;
this.sex = sex;
this.age = age;
this.weight=weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//你只需要在People里面写一次get/Set方法就行,这样Chinese类和Russian类都可以调用
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
private void print(int count){
System.out.println("父类中的私有化方法"+count);
}
public void show(int count){
print(count);
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Peple p=new Peple();
Chinese c=new Chinese();
//只需要子类修改了继承过来的属性和方法,看是否对父亲原来的属性和方法造成影响
System.out.println("使用父类对象调用show方法时");
p.show(8);
System.out.println("使用子类对象调用show方法后");
c.show(100);
System.out.println("再次使用父类对象调用show方法时");
p.show(8);
}
}
示例代码运行截图
3.3.4 类可以多层继承,直接继承的叫做父类,不直接继承的叫做间接父类
例如如下代码,类A继承类B,类B继承类C,类A也继承了类C的属性和方法,我们把类B叫做类A的直接父类,把类C叫做类A的间接父类
A类
class A extends B{
}
B类
class B extends C{
}
C类
class C{
}
3.3.5 如果一个类没显示的声明其父类时即类名后面没有接上extends关键字时,那么此类继承于java.lang.Object
示例代码
Chinese类
public class Chinese {
public Chinese() {
}
}
Test03类
public class Test03 {
public static void main(String[] args) {
Chinese c=new Chinese();
System.out.println(c.toString());
System.out.println(c.getClass());
}
}
分析
示例代码中的toString方法和getClass方法都是从Object处继承来的,因此才可以调用它