Java学习(下)

三、继承

继承:

继承是类与类的一种关系,是一种“is a”的关系。比如说,狗是一种动物(dog is an animal),汽车是一种交通工具(car is a vehicle),在这里动物和交通工具就称为父类(基类),狗和汽车就称为子类(派生类)。就像日常生活中我们所说的继承一样,儿子会继承父亲的一些相貌上或者性格上的特点,还会耳濡目染、有样学样地继承父亲的一些行为方式;而在Java中,子类则会继承父类所有的属性和方法(当然private修饰的属性和方法不可以继承哦)。
继承的关键字为extends具体定义语法为:

 [权限修饰符] class 类名 extends 父父类名{
    //定义或修改属性
    //定义或重写方法
}

注意:类是单继承的,即每个类只能有一个父类

方法的重写与方法的重载:

上面说过子类可以继承父类的方法,但如果父类中的方法不够完善或者不能满足子类的要求,这时候子类就可以修改父类的方法,拓展功能或者重新定义,这就是方法的重写。
在同一个类中,我们可以定义一些名称相同的方法,但这些方法的参数或者返回值类型却不同。在调用方法时,虽然这些方法都是同名的,但Java会根据不同的参数列表来选择正确的方法进行调用,这就是方法的重载。
方法的重写和重载从字面上来看只有一字之差,但是本质上却有很大的区别,以下是需要注意的几点:

  • 子类中重写的方法与父类中的方法有完全相同返回值类型方法名参数个数以及参数类型,只是方法体不同
  • 重载的方法必须具有不同的参数列表,即不同的参数类型或者不同的参数个数或者不同的参数顺序,因此方法体也就不同了。除此之外,权限修饰符和返回值类型也可以不同,但方法名必须要相同
  • 方法的重写和重载都可以改变权限修饰符,但都只能将范围扩大(关于权限修饰符的作用范围上文有介绍)
  • 一般来说,重载方法时,方法之间需要存在一定的联系,例如功能相似,因为这样才能使方法的重载有意义,并且提高程序的可读性
super关键字:

如果子类已经将父类中的方法重写了,调用的时候肯定是调用被重写过的方法,那如果现在一定要调用父类中的方法,此时就可以通过使用super关键字:super.方法名(参数列表)来实现

下面以狗类(子类)和动物类(父类)为例具体演示一下上面介绍的几个概念,先定义Dog类和Animal类:

package com.project;
public class Animal{//定义Animal类
    int legs = 2;//定义legs属性
    public void eat(){//定义eat方法 
        System.out.println("动物具有吃东西的能力");
}  


package com.project;
public class Dog extends Animal{//定义Dog类
}

修改项目测试类的代码:

    public class Test {
    public static void main(String[] args) {
        Dog obj = new Dog();//创建Dog类对象obj
        System.out.println(obj.legs);//输出obj的legs属性值
        obj.eat();//调用obj的eat()方法
    }
}

控制台界面会输出以下信息:

控制台显示

说明子类可以继承父类的属性和方法。

修改Dog类的代码:

  public class Dog extends Animal{
    int legs = 4;
    public void eat(){//重写eat()方法 
        super.eat();//用super关键字调用Animal类中的eat()方法
        System.out.println("狗具有吃骨头的能力");
      }
  }

其他代码不作改动,控制台界面会输出以下信息:

控制台显示

说明子类可以修改父类的属性和重写父类的方法。

四、多态

多态:

多态,从字面上理解就是多种形态,Java中指的是对象的多种形态。

多态分为两种:

  • 引用多态:父类的引用既可以指向本类的对象,也可以引用子类的对象
  • 方法多态:当通过父类创建本类对象时,调用的方法为本类的方法;创建子类对象时,调用的方法为子类继承的方法或重写的方法(即不能调用子类独有的方法)

还是以Dog类和Animal类为例,修改Dog类和项目测试类主方法的代码:

public class Dog extends Animal{
    public void eat(){
        System.out.println("狗具有吃骨头的能力");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal obj1 = new Animal();//通过Animal类创建Animal类对象obj1
        Animal obj2 = new Dog();//通过Animal类创建Dog类对象obj2(通过构造方法可以区别创建的是哪类对象)
        obj1.eat();//调用obj1的eat()方法
        obj2.eat();//调用obj2重写的eat()方法
    }
}

控制台界面会输出以下信息:

控制台显示

再次修改Dog类和项目测试类主方法的代码:

public class Dog extends Animal{
    public void eat(){
        System.out.println("狗具有吃骨头的能力");
    }
    public void watchDoor(){//定义watchDoor方法
        System.out.println("狗具有看门的能力");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal obj1 = new Animal();
        Animal obj2 = new Dog();
        obj1.eat();
        obj2.eat();
        obj2.watchDoor();//调用obj2的独有的watchDoor方法
    }
}

此时,obj2.watchDoor();这个地方程序会报错:

程序报错

因为父类中并没有定义watchDoor()方法,通过父类创建子类对象并调用这个子类独有的方法时就会报错。

抽象类:

抽象类只是规定子类必须拥有的方法,但并不规定这些方法是如何实现的。因此,可以从多个具有相同特征的类中抽象出一个抽象类,这个抽象类作为子类的模版,从而避免子类设计的随意性。需要注意的是:

  • 抽象类和抽象方法都是用abstract关键字来修饰
  • abstract定义抽象方法时,只需要声明即可,不需要定义具体实现(因为抽象类并不关注这些方法是如何实现的),即abstract 类名();//没有方法体
  • 抽象类中既可以有普通方法,也可以有抽象方法
  • 包含抽象方法的类一定是抽象类

下面以狗类(子类)、猫类(子类)和动物类(父类,同时也是抽象类)为例具体演示一下上面介绍的几个概念,先定义Dog类、Cat类和Animal类:

public abstract class Animal{//定义Animal抽象类
    public abstract void eat();//定义eat抽象方法
    public abstract void voice();//定义voice抽象方法 
}  

public class Dog extends Animal{
    public void eat(){//定义eat()方法在Dog类中的具体实现
        System.out.println("狗具有吃骨头的能力");
    }
    public void voice(){//定义voice()方法在Dog类中的具体实现
        System.out.println("狗“汪汪汪”地叫");
    }
}

public class Cat extends Animal{
    public void eat(){//定义eat()方法在Cat类中的具体实现
        System.out.println("猫具有吃鱼的能力");
    }
    public void voice(){//定义voice()方法在Cat类中的具体实现
        System.out.println("猫“喵喵喵”地叫");
    }
}

修改项目测试类的代码:

 public class Test {
    public static void main(String[] args) {
        Dog obj1 = new Dog();
        Cat obj2 = new Cat();
        obj1.eat();
        obj1.voice();
        obj2.eat();
        obj2.voice();
    }
}

控制台界面会输出以下信息:

控制台显示
接口:

接口定义的是某一批类所共同遵守的规范,既不关心这些类中的数据,也不关心这些类中方法的具体实现,只规定这些类中必须包含的方法(这一点与抽象类很相似)。
定义接口的关键字为interface。接口不同于类,它可以继承多个父接口。具体的定义语法为:

[权限修饰符] [abstract] interface 接口名 [extends 父接口1, 父接口2, ...]{
    //定义一个或多个常量
    //定义一个或多个抽象方法
}

注意:

  • 因为接口中包含的是常量和抽象方法,所以定义接口的时候系统会自动添加abstract关键字
  • 接口中的属性均为静态常量,因此在定义属性的时候系统会自动添加public static final修饰符
  • 接口中的方法均为抽象方法,因此在定义方法的时候系统会自动添加public abstract修饰符
  • 接口是用来被继承和被实现的,因此不能使用privateprotected修饰(这样会使得接口没有意义),一般使用public修饰

使用implements关键字实现接口。而当类既继承父类又实现接口时,定义语法为:

[权限修饰符] class 类名 extends 父类 implements 接口1, 接口2, ...{//一个类可以实现多个接口
    //如果继承了抽象类,要包含继承的抽象方法;此外还要包含接口的抽象方法
}

注意:

  • 在给接口命名的时候通常在名字前面加上一个“I”
  • 继承父类必须要在实现接口之前

还是以狗类、猫类为例,现在要他们都继承哺乳动物类。狗和猫都有吃东西和叫的能力,但狗能游泳而猫却不能。在大自然中,鸭子也是会游泳的,但很明显,鸭子并不属于哺乳动物,即不能继承哺乳动物类。因此要想描述狗和鸭子都具有游泳的能力,就要用到接口。

先定义ISwim接口:

package com.project;
public interface ISwim{
    public void swim();
}

定义Mammal类(定义的代码与Animal类一样,只是类名不同),修改Dog类和Cat类的代码,:

public class Dog extends Mammal implements ISwim{//实现ISwim接口
    public void eat(){
        System.out.println("狗具有吃骨头的能力");
    }
    public void voice(){
        System.out.println("狗“汪汪汪”地叫");
    }
    public void swim(){//定义swim()方法在Dog类中的具体实现
        System.out.println("狗具有游泳的能力");
    }
}

public class Cat extends Mammal{
    public void eat(){
        System.out.println("猫具有吃鱼的能力");
    }
    public void voice(){
        System.out.println("猫“喵喵喵”地叫");
    }
}

定义Duck类:

public class Duck implements ISwim{//实现ISwim接口
    public void swim(){//定义swim()方法在Duck类中的具体实现
        System.out.println("鸭子具有游泳的能力");
    }
}

修改项目测试类主方法的代码:

public class Test {
    public static void main(String[] args) {
        Dog obj1 = new Dog();
        Cat obj2 = new Cat();
        Duck obj3 = new Duck();
        obj1.eat();
        obj1.voice();
        obj1.swim();
        obj2.eat();
        obj2.voice();
        obj3.swim();
    }
}

控制台界面会输出以下信息:

控制台显示

后记

以上的内容是我通过看书和看视频以及上网找资料归纳、总结出来的,目的在于为我今后复习Java基础知识和编写Java程序时提供可查阅的笔记,我也希望能够给阅读本文的Java初学者一些帮助。

参考资料

《Java——从入门到精通》
慕课网(IMOOC)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容