【Java】7.0 继承 Inheritance
【简介】
通过类和对象,我们看到了如何非常有效地捕获代码中真实对象的属性和功能
我们常说,代码、对象是对现实的一种抽象反应,对吧
而继承,使我们可以一次又一次地重用代码,而不必重新编写代码。或者换句话说,可以让一些类被归于一种“有共性的模板”中
如果我们想编写类似的代码而只更改其中的一小部分怎么办?用继承!
通过继承,我们可以保留所需的功能和属性,然后为额外的内容编写新代码
在Java中,我们可以重用类定义并通过允许一个类(子类或子类)从另一个类(父类或超类)继承来扩展功能
【例子】
还是从车辆说起
我们知道所有车辆都会有一些与之相关的ID(车牌号),品牌和型号。现在让我们来考虑以下车辆:卡车,汽车和自行车————所有这些都具有与之相关的特征。
此外,一辆卡车将有一个承载能力(它可以合法承载的最大重量)和其它的轴,这是它和上述例子中的车辆相比,多出来的“额外功能”
虽然这三种工具是不一样的,但它们有一些共同的特性,我们使用继承作为表示此场景和访问这些特性的手段
这时候,我们就可以创建一个叫做Vehicle的超级类(super class)/父类(parent class),而Truck, Car,Bicycle 就是子类
在我们的示例中,Truck、Car和Bicycle类可以保留Vehicle超类的功能和属性,另外还有一些更具体的类以及它们独特的额外功能(一些方法等等)、
例如,在Car类中,它将具有来自Vehicle的所有方法,即getidNum()、getModel()、setModel()、toString()
它还可以具有特定的方法,例如setNoDoors(),getnoPassengers(),setNoPassengers()等等
这意味着尽管所有类都可以访问Vehicle中的方法和属性,但我们只需为它们编写一次代码(就是编写Vehicle的那次)
【着手使用继承】
让我们先为动物写一个统一的父类
public class Animal //superclass
{
//Attributes
private String breed;
private String colour;
private String owner;
//Default constructor
public Animal()
{
this.breed = "None";
this.colour = "Black";
this.owner = "Jane Doe";
}
//General Constructor
public Animal(String breed, String colour, String owner)
{
this.breed = breed;
this.colour = colour;
this.owner = owner;
}
//Getter and SEtter methods
public String getBreed()
{
return this.breed;
}
public String getColour()
{
return this.colour;
}
public String getOwner()
{
return this.owner;
}
public void setBreed(String breed)
{
this.breed = breed;
}
public void setColour(String colour)
{
this.colour= colour;
}
public void setOwner(String owner)
{
this.owner = owner;
}
//Functionality
public void speak()
{
System.out.println("Grr!");
}
public String toString()
{
String res = "************* \nBreed: " +
this.breed +"\nColour: " + this.colour + "\nOwner: " + this.owner;
return res;
}
}
然后我们想以此整一个Cat和Dog
这里我们使用Java关键字 extends
这使我们可以继承父(超级)类的所有属性和功能,从而扩展其设计
public class Dog extends Animal
{
//Attributes related to just Dog
private boolean chasesSquirrels;
//default constructor
public Dog(){
super(); // call superclass (ANIMAL) default constructor
this.chasesSquirrels = false;
}
}
有了继承之后,我们的代码简化了很多
Cat也是同理
public class Cat extends Animal
{
//Instance Variables
private boolean worksForSuperVillain;
//Default constructor
public Cat(){
//super(); // call Animal default constructor
this.worksForSuperVillain = false;
}
//General constructor
public Cat(String breed, String colour, String owner, boolean worksForSuperVillain){
super(breed,colour,owner);
this.worksForSuperVillain = worksForSuperVillain;
}
}
【覆盖和添加功能】
一些关于子类父类的规定:
1.我们可以覆盖超类方法的行为,并在当前提供的功能之上添加我们自己的功能
2.我们甚至可以用全新的子类行为替换现有的超类功能
要覆盖超类方法并更改其内容,我们只需在子类中重新编写相同的方法即可,这需要我们在子类中保持相同(或相似)的方法签名
看看在Animal父类中的speak方法:
public void speak()
{
System.out.println("Grr!");
}
而在我们的子类Dog中,我们编写了相同的方法签名,但是这个方法与Animal中的相比,它具有不同的方法内容
public void speak()
{
System.out.println("Woof woof!");
}
需要注意的是,如果我们重写了超类中一个方法,则被重写方法的访问修饰符不能比对其进行重写的方法更严格。(也就是子类重写时,修饰符不能比父类的对应方法严格)
我们的Vehicle父类有两个实例变量,除了类中的所有方法外,还可以传递给子类
注意我们的每个子类的构造函数是,如何使用super()方法,从Vehicle类调用不同的构造函数的。比如:
public Dog()
{
super(); // call superclass (ANIMAL) default constructor
this.chasesSquirrels = false;
}
public Dog(String breed, String colour, String owner, boolean chasesSquirrels)
{
super(breed,colour,owner); //Call general constructor in Animal classs
this.chasesSquirrels = chasesSquirrels;
}
【小结】
1.Java允许我们重用类定义并通过允许一个类(子类或子类)从另一类(父类或超类)继承来扩展功能-这称为继承
2.使用继承时,超类的所有属性和方法在每个子类中均可用
3.关键字extends允许一个类从另一个类进行继承
4.为了调用超类构造函数,我们使用关键字super()
5.我们可以覆盖超类方法的行为,并在当前提供的功能之上添加我们自己的功能
【补充:super()】
super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类
与 this 类似,super 相当于是指向当前对象的父类,这样就可以用 super.xxx 来引用父类的成员。因为我们前面说过了,子类可以重写父类的方法。
(子类中的成员变量或方法与父类中的成员变量或方法同名)
当我们有的时候向调用二者同名的方法时,调用父类的需要使用super,否则根据子类优先的原则,会调用子类的对应方法。
super():调用父类中的某一个构造函数(应该为构造函数中的第一条语句),在圆括号中可以写上对应参数
(关于super,这里仅仅是作了一点小小的补充。super和this类似,还有其它的使用方法,这个就不在本篇说了)