封装、多态和继承是面向对象编程的三大特性
除了以上三大特征,我们也要熟悉其他概念,例如包,组合,抽象类,接口等。
封装
<<
代码大全
>>
开篇就在讨论一个问题
:
软件开发的本质就是对程序复杂程度的管理
.
如果一个软件代码复杂程
度太高
,
那么就无法继续维护
.
如何管理复杂程度
?
封装就是最基本的方法
.
在我们写代码的时候经常会涉及两种角色
:
类的实现者
和
类的调用者
.
封装的本质就是让类的调
用者不必太多的了解类的实现者是如何实现类的, 只要知道如何使用类就行了.这样就降低了类使用者的学习和使用成本
,
从而降低了复杂程度。
private实现封装
private/ public 这两个关键字表示 "访问权限控制"
被
public
修饰的成员变量或者成员方法
,
可以直接被类的调用者使用
.
被
private
修饰的成员变量或者成员方法
,
不能被类的调用者使用.
包
包(package)是组织类的一种方式
使用包主要目的是保证类的唯一性
可以使用import语句导入包,如果需要java.util中的其他类,可以使用ipmore java.util.*(但是是我们更建议显式的指定要导入的类名. 否则还是容易出现冲突的情况.)
包的访问权限控制
我们已经了解了类中的
public
和
private. private
中的成员只能被类的内部使用
.
如果某个成员不包含
public
和
private
关键字
,
此时这个成员可以在包内部的其他类使用
,
但是不能在包外部的类使用
.
常见的系统包
1. java.lang:
系统常用基础类
(String
、
Object),
此包从
JDK1.1
后自动导入。
2. java.lang.reflflect:java
反射编程包
;
3. java.net:
进行网络编程开发包。
4. java.sql:
进行数据库开发的支持包。
5. java.util:
是
java
提供的工具程序包。
(
集合类等
)
非常重要
6. java.io:I/O
编程开发包。
继承
背景
代码中创建的类
,
主要是为了抽象现实中的一些事物
(
包含属性和方法
).
有的时候客观事物之间就存在一些关联关系
,
那么在表示成类和对象的时候也会存在一定的关联
.
例如
,
设计一个类表示动物
// Animal.java
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
// Cat.java
class Cat {
public String name;
public Cat(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
// Bird.java
class Bird {
public String name;
public Bird(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
public void fly() {
System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
}
}
这个代码我们发现其中存在了大量的冗余代码。 此时我们就可以让 Cat 和 Bird 分别继承 Animal 类, 来达到代码重用的效果。
此时
, Animal
这样被继承的类
,
我们称为
父类
,
基类
或
超类
,
对于像
Cat
和
Bird
这样的类
,
我们称为
子类
,
派生类和现实中的儿子继承父亲的财产类似
,
子类也会继承父类的字段和方法
,
以达到代码重用的效果。
语法规则
使用
extends
指定父类
.
Java
中一个子类只能继承一个父类.(单继承语言)
子类会继承父类的所有
public
的字段和方法.
对于父类的
private
的字段和方法
,
子类中是无法访问的
.
子类的实例中
,
也包含着父类的实例
.
可以使用
super
关键字得到父类实例的引用.
此时对于上面的代码我们就可以使用继承改进
class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
class Cat extends Animal {
public Cat(String name) {
// 使用 super 调用父类的构造方法.
super(name);
}
}
class Bird extends Animal {
public Bird(String name) {
比特科技
super(name);
}
public void fly() {
System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("小黑");
cat.eat("猫粮");
Bird bird = new Bird("圆圆");
bird.fly();
}
}
如果我们把
name
改成
private,
那么此时子类就不能访问了,此时我们就可以使用protected关键字.
protected关键字
刚才我们发现
,
如果把字段设为
private,
子类不能访问
.
但是设成
public,
又违背了我们
"
封装
"
的初衷
.两全其美的办法就是
protected
关键字。
对于类的调用者来说
, protected
修饰的字段和方法是不能访问的
对于类的
子类
和
同一个包的其他类
来说
, protected
修饰的字段和方法是可以访问的
小结
: Java
中对于字段和方法共有四种访问权限
private:
类内部能访问
,
类外部不能访问
默认
(
也叫包访问权限
):
类内部能访问
,
同一个包中的类可以访问
,
其他类不能访问
.
protected:
类内部能访问
,
子类和同一个包中的类可以访问
,
其他类不能访问
.
public :
类内部和类的调用者都能访问
访问权限:public>protected>default>private
final
关键字
final 关键字的功能是 限制 类被继承
组合
和继承类似
,
组合也是一种表达类之间关系的方式
,
也是能够达到代码重用的效果。
组合表示
has
-
a
语义
继承表示
is
-
a
语义
多态(难点)
向上转型
子类对象/引用 给父类就称为向上转型。
注:向上转型之后 只能通过父类的引用访问父类自己特有的方法和属性,不能访问子类特有的属性和方法
向下转型(不推荐)
向上转型是子类对象转成父类对象
,
向下转型就是父类对象转成子类对象
.
相比于向上转型来说
,
向下转型没那么常见
,但是也有一定的用途
动态绑定(运行时绑定)
满足条件:1.向上转型 2.通过父类引用调用父类和子类的同名覆盖方法,此时就会发生运行时绑定。那么覆盖又是什么意思呢?
方法重写
子类实现父类的同名方法
,
并且参数的类型和个数完全相同
,
这种情况称为
覆写
/
重写
/
覆盖
(Override)
注意事项:
1.重写中子类的方法的访问权限不能低于父类的方法访问权限
.
2.重写的方法返回值类型不一定和父类的方法相同
(
但是建议最好写成相同
,
特殊情况除外
)
3.普通方法可以重写
, static
修饰的静态方法不能重写
.
4.private方法也不可以重写
5.如果一个方法被final修饰,也不可以被重写
理解多态
多态顾名思义, 就是 "一个引用, 能表现出多种不同形态"
无论是哪种编程语言
,
多态的核心都是让调用者
不必关注对象的具体类型
.
这是降低用户使用成本的一种重要方式
。