一、封装
定义
在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
目的
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点
- 良好的封装能够减少耦合。
- 类内部的结构可以自由修改。
- 可以对成员变量进行更精确的控制。
- 隐藏信息,实现细节。
实现
1、属性封装
修改属性的可见性来限制对属性的访问(一般限制为private),例如:
public class Person {
private String name;//private封装属性
private int age;
}
2、访问方法
对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
二、继承
定义
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
目的
- 继承的出现提高了代码的复用性,提高软件开发效率。
- 继承的出现让类与类之间产生了关系,提供了多态的前提。
类与类的3种关系:
is a :继承关系,例如:公共汽车 is a 汽车
use a:使用关系,例如:人 use a 钳子
has a:包含关系,例如:人has a 胳膊
实现
使用extends关键字
class 子类 extends 父类 {
}
案例:公司有2个部门,人事部和研发部,各自属性如下
定义部门类
/**
* 部门父类:存放所有子类共性的内容
*/
public class Deparment {
private int ID;// 部门编号
private String name = "待定";// 部门名称
private int amount = 0;// 部门人数
private String responsibility = "待定";// 部门职责
private String manager = "无名氏";// 部门经理
省略了get和set
定义人事部
/**
* 人事部
*/
public class PersonalDepartment extends Deparment{
private int count;//招聘人数
public PersonalDepartment() {
}
public PersonalDepartment(int count) {
this.count = count;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
定义研发部
/**
* 研发部
*/
public class ResourceDepartment extends Deparment{
private String speciality =null;//研发方向
public ResourceDepartment() {
}
public ResourceDepartment(String speciality) {
this.speciality = speciality;
}
public String getSpeciality() {
return speciality;
}
public void setSpeciality(String speciality) {
this.speciality = speciality;
}
}
测试公司类
/**
* 公司类
*/
public class Company {
public static void main(String[] args) {
//创建人事部对象
PersonalDepartment personalDepartment = new PersonalDepartment();
//创建研发部对象
ResourceDepartment resourceDepartment = new ResourceDepartment();
//调用父类的方法
System.out.println(personalDepartment.getName()); //getName()是父类的
System.out.println(resourceDepartment.getName()); //getName()是父类的
}
}
继承注意事项
类只支持单继承,不允许多继承
class A{}
class B{}
class C extends A,B{} // C类不可以同时继承A类和B类
多个类可以继承一个父类
class A{}
class B extends A{}
class C extends A{} // 类B和类C都可以继承类A
允许多层继承
class A{}
class B extends A{} // 类B继承类A,类B是类A的子类
class C extends B{} // 类C继承类B,类C是类B的子类,同时也是类A的子类
子类和父类是一种相对概念
也就是说一个类是某个类父类的同时,也可以是另一个类的子类。例如上面的这种情况中,B类是A类的子类,同时又是C类的父类。
Object是所有类的父类
如果一个类没有显示定义父类,那么默认继承Object类
三、多态
定义
多态是同一个行为具有多个不同表现形式或形态的能力。同一个事件发生在不同的对象上会产生不同的结果。
多态的优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
实现
多态的实现方法有两种
- 方法重写(公认的多态)
- 方法重载(非公认的多态)
多态存在的三个必要条件
继承;重写;父类引用指向子类对象:Parent p = new Child();
普通类实现多态
- 普通类多态定义的格式
父类 变量名 = new 子类();
例如:
class Fu {}
class Zi extends Fu {}
Fu f = new Zi();//类的多态使用
抽象类实现多态
- 抽象类多态定义的格式
抽象类 变量名 = new 抽象类子类();
例如:
abstract class Fu {
public abstract void method();
}
class Zi extends Fu {
public void method(){
System.out.println(“重写父类抽象方法”);
}
}
Fu fu= new Zi();//类的多态使用
接口实现多态
- 接口多态定义的格式
接口 变量名 = new 接口实现类();
例如:
interface Fu {
public abstract void method();
}
class Zi implements Fu {
public void method(){
System.out.println(“重写接口抽象方法”);
}
}
Fu fu = new Zi();//接口的多态使用
- 注意事项
同一个父类的方法会被不同的子类重写。父类引用在调用方法时,调用的为各个子类重写后的方法。
Person p1 = new Student();
Person p2 = new Teacher();
p1.work(); //p1会调用Student类中重写的work方法
p2.work(); //p2会调用Teacher类中重写的work方法
当变量名指向不同的子类对象时,由于每个子类重写父类方法的内容不同,所以会调用不同的方法。
方法重载实现多态
class Student {
public void doWork(){
System.out.println(" is working ...");
}
public void doWork(Date from ,Date end){
SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(" from "+ sdf.format(from) +"... end "+ sdf.format(end) +"... working....");
}
}
public class TestInstanceof {
public static void main(String[] args) {
Student student = new Student();
student.doWork();//第1种重载(第1种多态)
student.doWork(new Date(1658972077239L),new Date(1658973187239L));//第2种重载(第2种多态)
}
}
多态的转型
多态的转型分为向上转型与向下转型两种:
- 向上转型就是父类引用指向子类对象
- 向下转型就是子类引用指向父类对象
向上转型
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式:
父类类型 变量名 = new 子类类型();
例如:
Person p = new Student();
向下转型
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。
如果是直接创建父类对象,是无法向下转型的!
使用格式:
子类类型 变量名 = (子类类型) 父类类型的变量;
例如
Student stu = (Student) p; //变量p 实际上指向Student对象
多态的好处和弊端
当父类的引用指向子类对象时,就发生了向上转型,即把子类类型对象转成了父类类型。向上转型的好处是隐藏了子类类型,提高了代码的扩展性。
但向上转型也有弊端,只能使用父类共性的内容,而无法使用子类特有功能,功能有限制。