第三部分:java消息、继承与多态

一:消息

1.消息的概念:

对象之间的联系是通过消息传递来实现的。把发消息的对象称为发送者,把接受消息的对象称为接收者。消息就是向对象发出服务请求,是对数据成员和成员方法的引用。消息性质:
(1)同一对象可接收不同形式的多个消息,产生不同的响应。
(2)相同形式的消息可以发送给不同的对象,各对象所作出的响应可以是截然不同的。
(3)消息的发送可以不考虑具体的接收者,对象可以相应消息,也可以对消息不予理会,对消息的响应并不是必须的。

2.公有消息和私有消息

在面向对象系统中,消息分为两类:公有消息和私有消息。当有一批消息同属于一个对象时,由外界对象直接发送给这个对象的消息称为共有消息;对象发送给自己的消息称为私有消息。私有消息对外不开放。
特定于对象的消息可分为以下三种类型:
(1)可以返回对象内部状态的消息。
(2)可以改变对象内部状态的消息。
(3)可以做一些特定操作,改变系统状态的消息。

二:访问控制

当一个类被声明为 public 时,其他包中的public程序可使用 import 语句可以引用这个 public 类。
访问控制规则见下表:

数据成员与方法\类 public 缺省
public 所有类 包中类(含当前类)
protected 包中类(含当前类),所有子类 包中类(含当前类)
缺省(friendly) 包中类(含当前类) 包中类(含当前类)
private 当前类本身 当前类本身

三:多态机制

多态是面向对象系统中的又一重要特性,它描述的是同名方法可以根据发送消息的对象传送参数的不同,采取不同的行为方式的特性。

1.概念

多态是指一个程序中具有相同名字而内容不同的方法共存的情况。
java中提供了两种多态机制。:重载和覆盖。
重载:
在同一类中定义了多个同名而不同内容的成员方法时,我们称这些方法是重载(override)的方法。
重载的方法主要通过形式参数列表中参数的个数、参数的数据类型和参数的顺序(java特有)等方面的不同来区分。
覆盖:
继承机制中,java允许子类对父类的方法重新定义,即在子类中可以定义与父类中已定义的方法同名而内容不同的方法。这种多态被称为覆盖(overload)。
在方法引用时指明引用的是父类的方法还是子类的方法来区分。

2.继承

java用extends指明继承关系。子类可以从父类那里继承所有非private的属性和方法。
在定义一个类而不给出 extends 关键字及父类名时,默认这个类是系统类object的子类。
(1)数据成员的继承
子类可以继承父类的所有非私有数据成员。
数据成员的隐藏:
在子类中重新定义一个与父类中已定义的数据成员名完全相同的数据成员。
即子类拥有了两个相同名字的数据成员,一个来自父类,一个是自己定义的。当子类引用这个数据成员时默认引用它自己定义的数据成员,把父类的“隐藏”起来。
当子类要引用继承自父类的同名数据成员时,可使用关键字 super 引导。
(2)成员方法的继承
子类可以继承父类的所有非私有数据成员。
成员方法的覆盖
方法的覆盖与数据成员的隐藏不同之处在于:父类同名的数据成员在子类对象中仍占有自己独立的内存空间;子类方法对父类同名方法的覆盖将清除父类方法占用的内存,使父类方法在子类对象中不复存在。
注意:
子类在重新定义父类已有的方法时,应保持与父类完全相同的方法名、返回值类型和参数列表,否则就不是方法的覆盖,而是子类定义的特有方法,与父类方法无关。
(3) this 和 super
this 使用场合:
(1)用来访问当前对象的数据成员,使用形式:this.数据成员
(2)用来访问当前对象的成员方法,使用形式:this.成员方法(参数)
(3)当有重载的构造方法时,用来引用同类的其他构造方法,使用形式:this(参数)

//构造方法的重载
class Address{
    public int x=0,y=0,z=0;
    //以下是同名不同参的构造方法
    Address(int x){//可重载的构造方法1
        this.x=x;
    }
    Address(int x,int y){//可重载的构造方法2
        this(x);//当前构造方法调用可重载的构造方法1
        this.y=y;
    }
    Address(int x,int y,int z){//可重载的构造方法3
        this(x,y);//当前构造方法调用可重载的构造方法2
        this.z=z;
    }
    public int add(){
        return x+y+z;
    }
}
public class C5_14{
    public static void main(String arg[]){
        Address p1=new Address(2,3,5);
        Address p2=new Address(10,20);
        Address p3=new Address(1);
        System.out.println(p1.add());
        System.out.println(p2.add());
        System.out.println(p3.add());
    }
}
运行结果

super 使用方法:
(1)用来访问直接父类隐藏的数据成员,使用形式:super.数据成员
(2)用来调用直接父类中被覆盖的成员方法,使用形式:super.成员方法(参数)
(3)用来调用直接父类的构造方法,使用形式:super(参数)

//P119构造方法的继承
class Address{
    public int x=0,y=0,z=0;
    //以下是同名不同参的构造方法
    Address(int x){//可重载的构造方法1
        this.x=x;
    }
    Address(int x,int y){//可重载的构造方法2
        this(x);//当前构造方法调用可重载的构造方法1
        this.y=y;
    }
    Address(int x,int y,int z){//可重载的构造方法3
        this(x,y);//当前构造方法调用可重载的构造方法2
        this.z=z;
    }
    public int add(){
        return x+y+z;
    }
}
public class C5_15 extends Address{
    int a=0,b=0,c=0;
    C5_15(int x){
        super(x);
        a=x+7;
    }
    C5_15(int x,int y){
        super(x,y);
        a=x+5;
        b=y+5;
    }
    C5_15(int x,int y,int z){
        super(x,y,z);
        a=x+4;
        b=y+4;
        c=z+4;
    }
    public int add(){
        System.out.println("super:x+y+z="+super.add());
        return a+b+c;
    }
    public static void main(String arg[]){
        C5_15 p1=new C5_15(2,3,5);
        C5_15 p2=new C5_15(10,20);
        C5_15 p3=new C5_15(1);
        System.out.println(p1.add());
        System.out.println(p2.add());
        System.out.println(p3.add());
    }
}
运行结果

3.向方法传递对象

传递方法的参数如果是变量,只能由实参传递给形参,而不能由形参带回,即单向值传递,在方法的引用过程中,对于形参变量值的修改并不影响实参变量值。
传递方法的参数如果是对象,则实参与形参的对象的引用指向同一个对象,成员方法中对对象的数据成员的修改,会使实参对象的数据成员值也发生同样的变化。这种参数的传递方式被称为“双向地址传递”。

class Student{
    public String Name;
    public int age=16;
    public int score=0;
    public void ShowStudent(){
        System.out.println("Name:"+Name);
        System.out.println("age:"+age);
        System.out.println("score:"+score);
    }
    public void A(Student s,String Name,int age,int score){
        s.Name=Name;
        s.age=age;
        s.score=score;
    }
}
public class C5_16 extends Student{
    public static void main(String arg[]){
        Student st1=new Student();
        Student st2=new Student();
        st1.A(st1,"Zhang",23,81);
        st2.A(st2,"Li",24,90);
        st1.ShowStudent();
        st2.ShowStudent();
    }
}
运行结果

4.继承与封装的关系

继承机制的引入丝毫没有影响对象的封装性。
封装性主要指的是对象的封装性,即将属于某一类的一个具体的对象封装起来,使其数据和操作称为一个整体。继承是一种静态共享代码的手段,通过派生类对象的创建,可以接受某一消息,启动其基类所定义的代码段,从而使基类和派生类共享这一段代码。封装机制所提供的是一种动态共享代码的手段,通过封装,我们可以将一段代码定义在一个类中,在另一个类所定义的操作中,可以通过创建该类的实例,并向它发送消息而启动这一段代码,达到共享的目的。

四:抽象类、接口与包

抽象类体现数据抽象的思想,是实现程序多态性的一种手段。接口是java中实现多重继承的唯一途径。

1.抽象类

抽象类是它的所有子类公共属性的集合。
抽象类与抽象方法的限制如下:
(1)凡是用 abstract 修饰符修饰的类被称为抽象类。凡是用 abstract 修饰符修饰的成员方法被称为抽象方法。
(2)抽象类中可以有零个或多个抽象方法,也可以包含非抽象的方法。
(3)抽象类中可以没有抽象方法,但是有抽象方法的类必须是抽象类。
(4)对于抽象方法来说,在抽象类中只指定其方法名及其类型,而不书写其实现代码。
(5)抽象类可以派生子类,在抽象类派生的子类中,必须实现抽象类中定义的所有抽象类方法。
(6)抽象类不能创建对象,只能由抽象类派生的子类创建对象。
(7)如果父类中已有同名的 abstract 方法,则子类中就不能再有同名的抽象方法。
(8)abstract 不能与 final 并列修饰同一个类。
(9)abstract 不能与private、static、final、或 native 并列修饰同一个方法。

2.接口

声明接口:

[修饰符] interface 接口名 [extends 父接口名列表]{
    常量数据成员声明
    抽象方法声明
}

说明;
(1)interface 是声明接口的关键字,可以把它看成一个特殊类。
(2)接口名要符合 java 标识符规定。
(3)修饰符有 public 和默认。
public 修饰的接口:公共接口,可被所有的类和接口使用;
默认:只能被同一个包中的其他类和接口使用。
(4)接口也具有继承性,用 extends 声明,与类的继承不同的是,一个接口可以有一个以上的父接口,它们之间用逗号分隔。
(5)常量数据成员声明:常量数据成员前有没有修饰符都可以。修饰符是 public static 和 final static ;注意接口中的数据成员都是用 final 修饰的常量,写法如下:
修饰符 数据成员类型 数据成员名=常量值

数据成员名=常量值
(6)抽象方法声明。接口中的方法都是用abstract 修饰的抽象方法,默认为 public abstract 方法。所以接口的本质是抽象类。
定义接口注意事项:
接口没有自身的构造方法,所有成员方法都是抽象方法。
类实现接口的注意事项:
接口定义仅仅是实现某一特定功能的对外接口和规范,而不能真正实现这个功能,真正的实现是在“继承”这个接口的各个类完成的。所以在 java 中,把对接口功能的继承称为“实现”。
(1)在类中,用 implements 关键字就可以调用接口。一个类若要调用多个接口,可在 implements 后用逗号隔开多个接口的名字。
(2)如果实现某接口的类不是 abstract 的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,并且方法头部分应该与接口中的定义完全一致。
(3)如果实现某接口的类是 abstract 的抽象类,则它可以不实现指定接口的所有抽象方法。但是对于这个抽象类的任何一个非抽象的子类而言,它们父类所实现的接口中的抽象方法都必须有实现的方法体,这些方法可以来自抽象的父类,也可以来自子类自身,但是不允许存在未被实现的接口方法,这主要体现了非抽象类中不能存在抽象方法的原则。
(4)接口的抽象方法的访问限制符都已被指定为 public ,所以类在实现方法时,必须显示的使用 public 修饰符,否则缩小了接口中定义的方法的访问控制范围。

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

推荐阅读更多精彩内容

  • 一:java概述: 1,JDK:Java Development Kit,java的开发和运行环境,java的开发...
    慕容小伟阅读 1,779评论 0 10
  • 本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-java.h...
    eddy_wiki阅读 1,198评论 0 5
  • 整理来自互联网 1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具...
    Ncompass阅读 1,537评论 0 6
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • 1.import static是Java 5增加的功能,就是将Import类中的静态方法,可以作为本类的静态方法来...
    XLsn0w阅读 1,219评论 0 2