面向对象
面向对象的两个概念
封装
封装(encapsulation)是指一种将类实现细节部分包装,隐藏起来的方法
封装方式: 类
对类的内部状态的访问进行控制,只提供应该提供的信息
把代码分成两个部门: 接口 和 实现
接口因为涉及和外部的交互,对用户暴露,应该保持稳定,不轻易修改,新的接口可以是对旧接口的扩展,但旧接口应该保留。例如: API和库
内部实现不需要暴露给外部用户,在接口功能不被影响的前提下,可以随意修改和重构
良好的封装是解耦的基础
继承
继承是面向对象编程技术的一块基石,因为它允许创建分等级层次的类封装方式: 类
子类继承父类的特征和行为,使得子类对象具有父类对象的特征和方法
继承需要符合一个关系: is-a, 子类应该是更具体的父类
子类拥有父类非private的成员变量和方法
子类可以拥有自己的成员变量和方法,即子类可以对父类进行扩展
子类可以重新实现父类的方法,override
Java中:
只支持单继承,即只能有一个父类
在声明子类的时候,通过关键字“extends”表达继承,且不允许多
super关键字:可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类
this关键字: 指向自己的引用
构造方法
- 子类不能继承父类的构造器(构造方法或者构造函数),如果父类的构造器带有参数,则必须在子类的构造器中显式地通过super关键字调用父类的构造器并配以适当的参数列表
- 如果父类构造器没有参数,则在子类的构造器中不需要使用super关键字调用父类构造器,系统会自动调用父类的无参构造器
多态
- 多态表示一个类型(父类或者接口)的变量的方法的具体实现行为由变量指向的具体对象确定
- 实现有三个必要条件:
- 继承或接口
- override父类的方法
- 父类数据类型的引用指向子类对象
多态成员的访问特点:
- 成员变量: 编译看左边(父类),运行看左边(父类)
- 成员方法:编译看左边(父类),运行看右边(子类) --动态绑定
- 静态方法: 编译看左边(父类),运行看左边(父类)(静态和类相关,算不上重写,所以,访问还是左边的)
只有非静态的成员方法,编译看左边,运行看右边
便利性: 开发中一般是利用多态声明形式参数,并将创建子类的匿名对象作为实际参数,一定程度上可以避免重载。 多态的向下调整和向上调整特性,让其更灵活
// 比如有两个读新闻子类, urlReader和videoReader, 他们都继承newsReader且override了父类的readNews方法。
public void read(newsReader news){
newsReader.readNews()
}
弊端,就是多态,不能使用子类特有的成员属性和子类特有的成员方法
Animal animal = new Cat();
// 猫有个抓老鼠的方法,但是这里是无法使用的
Cat cat = (Cat)animal;
// 强制引用转换
cat.catchMouse();
// ok
引用知乎的一个花木兰替父从军的故事帮助记忆:
大家都知道花木兰替父从军的例子,花木兰替父亲花弧从军。那么这时候花木兰是子类,花弧是父类。花弧有自己的成员属性年龄,姓名,性别。花木兰也有这些属性,但是很明显二者的属性完全不一样。花弧有自己的非静态成员方法‘骑马杀敌’,同样花木兰也遗传了父亲一样的方法‘骑马杀敌’。花弧还有一个静态方法‘自我介绍’,每个人都可以问花弧姓甚名谁。同时花木兰还有一个自己特有的非静态成员方法‘涂脂抹粉’。但是,现在花木兰替父从军,女扮男装。这时候相当于父类的引用(花弧这个名字)指向了子类对象(花木兰这个人),那么在其他类(其他的人)中访问子类对象(花木兰这个人)的成员属性(姓名,年龄,性别)时,其实看到的都是花木兰她父亲的名字(花弧)、年龄(60岁)、性别(男)。当访问子类对象(花木兰这个人)的非静态成员方法(骑马打仗)时,其实都是看到花木兰自己运用十八般武艺在骑马打仗。当访问花木兰的静态方法时(自我介绍),花木兰自己都是用她父亲的名字信息在向别人作自我介绍。并且这时候花木兰不能使用自己特有的成员方法‘涂脂抹粉’。-----多态中的向上转型
那么终于一将功成万骨枯,打仗旗开得胜了,花木兰告别了战争生活。有一天,遇到了自己心爱的男人,这时候爱情的力量将父类对象的引用(花弧这个名字)强制转换为子类对象本来的引用(花木兰这个名字),那么花木兰又从新成为了她自己,这时候她完全是她自己了。名字是花木兰,年龄是28,性别是女,打仗依然那样生猛女汉子,自我介绍则堂堂正正地告诉别人我叫花木兰。
OMG!终于,终于可以使用自己特有的成员方法‘涂脂抹粉’了。从此,花木兰完全回到了替父从军前的那个花木兰了。并且和自己心爱的男人幸福的过完了一生。-----多态中的向下转型
Java 类模型
类: 类是一个模板,它描述一类对象的行为和状态
对象: 对象是类的一个实例,有具体的状态
方法: 类中定义的该类的实例对象所具有的行为
静态方法: 隶属于类本身的方法
Java里的常量和变量都对应于一个对象,这个对象的行为和具有的属性是由类来定义的
Java程序的基本结构就是一系列类的定义,类之间的关系和具体类的对象之间的互相操作
Java方法和成员变量
方法: 类中定义的该类的实例对象所具有的的行为
静态方法: 隶属于类本身的方法
一个方法由“方法名 + 参数类型” 决定
相同方法名,不同参数类型,是不同的方法
<返回类型> 方法名(<参数类型> 参数名, ...) { 代码; return <返回值> }
可以用修饰符控制方法和成员变量的作用域
权限 | public | private | default | private |
---|---|---|---|---|
同一个类 | OK | OK | OK | OK |
同一个包 | OK | OK | OK | NO |
子父类 | OK | OK | NO | NO |
不同包 | OK | NO | NO | NO |
抽象类和接口
抽象类表达的是两种类之间有某种从属关系,比如动物和人的关系,人是一种动物。 但是动物是无法在现实中具象的,但是动物是有很多抽象方法的,比如跑,睡觉,吃饭。人作为抽象类的子类,具体定义了这些方法的实现
接口表达的是该类具有某种特征,比如人是可以实现行走的接口
语义上,抽象类是继承的一种,而接口只是定义类应该具有的行为特征