前一篇:
这一篇还是来分享继承。
super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName
如何使用呢
class Mantou extends Food{
@Override
public String toString() {
return birthcity+super.birthcity;
}
}
实际上,这里使用super.name,或者this.name,或者name,效果都是一样的。编译器会自动定位到父类的name字段。
public class main {
public static void main(String[] args) {
Mantou hello = new Mantou();
hello.setBirthcity("beijing");
System.out.println(hello.toString());
}
}
打印下,输出结果是
但是,在某些时候,就必须使用super,例如
public class main {
public static void main(String[] args) {
Mantou hello = new Mantou("beijing",10,10);
}
}
class Mantou extends Food{
protected int score;
public Mantou(String bir,float price,int score){
this.score=score;
}
}
但是我们在写完代码,编辑器就给报错了
结果
但是应该怎么做呢
public class main {
public static void main(String[] args) {
Mantou hello = new Mantou("beijing",10,10);
System.out.println(hello.getBirthcity());
}
}
class Mantou extends Food{
protected int score;
public Mantou(String bir,float price,int score){
super(bir,price);
this.score=score;
}
}
因为在Java中,任何class的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();,所以,Mantou类的构造方法实际上是这样。
父类的构造方法中需要参数,上面的父类就需要构造参数。就需要在super中传递参数。
父类的代码如下:
class Food {
protected String birthcity;
protected float price;
public Food(String birthcity, float price) {
this.birthcity = birthcity;
this.price = price;
}
public String getBirthcity() {
return birthcity;
}
public void setBirthcity(String birthcity) {
this.birthcity = birthcity;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
假如在super中不传递参数
执行也会报错
这个告诉我们,必须要传递对应的参数,调用父类的构造方法
class Mantou extends Food{
protected int score;
public Mantou(String bir,float price,int score){
super(bir,price);
this.score=score;
}
}
从上面的执行中,可以看到:
父类没有默认的构造方法,子类就必须super()并给出参数以便让编译器定位到父类的一个合适的构造方法。
子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。
如果一个引用变量的类型是
public class main {
public static void main(String[] args) {
Mantou hello = new Mantou();
System.out.println(hello.getClass());
}
}
结果输出就是一个
如果 变量指向的是Food
public class main {
public static void main(String[] args) {
Food food = new Food();
System.out.println(food.getClass());
}
}
结果是
现在问题来了:如果Mantou是从Food继承下来的,那么,一个引用类型为Food的变量,能否指向Mantou类型的实例?
public class main {
public static void main(String[] args) {
Food food = new Mantou();
System.out.println(food.getClass());
}
}
结果
测试一下就可以发现,这种指向是允许的!
这是因为Mantou
继承自Food,因此,它拥有Food
的全部功能。Food
类型的变量,如果指向Mantou
类型的实例,对它进行操作,是没有问题的!
这种把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting)。
向上转型实际上是把一个子类型安全地变为更加抽象的父类型:
Mantou s = new Mantou();
Food p = s; // up, ok
Object o1 = p; // up, ok
和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)
public class main {
public static void main(String[] args) {
Food food = new Mantou();
Mantou mantou= (Mantou) food;
System.out.println(mantou.getClass());
}
}
结果
但是 也会有失败的时候。
public class main {
public static void main(String[] args) {
Food food = new Food();
Mantou mantou= (Mantou) food;
System.out.println(mantou.getClass());
}
}
执行下
这样是不可以的。那么如何避免呢
为了避免向下转型出错,Java提供了instanceof操作符,可以先判断一个实例究竟是不是某种类型:
public class main {
public static void main(String[] args) {
Food food = new Food();
if (food instanceof Mantou){
Mantou mantou= (Mantou) food;
System.out.println(mantou.getClass());
}
}
}
结果
编译通过
instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null,那么对任何instanceof的判断都为false。
所以可以利用上面写的if判断,正确后再向下转型。
知识点就分享完毕了。简单实现一个继承。在Mantou类在实现一个Tianmantou,让它增加一个字段 islike
class Tianmantou extends Mantou{
protected boolean islike;
public boolean isIslike() {
return islike;
}
public void setIslike(boolean islike) {
this.islike = islike;
}
}
其实很简单,继承在后续的面向对象的编程中会大量的使用。一些概念大家要牢记。