## 一、封装
### 1.1 为什么要封装
- 有些数据语法上是可以的,在生产中是非法的
- 年龄20000
- 工资-10000
### 1.2 封装的流程
> 1、私有化属性【private】
>
> 2、提供公开的setXxx和getXxx方法
>
> 3、在方法中制定访问规则
### 1.3 封装案例
#### Student
```
package com.shine.private0;
/**
* 类名
* Student
* 属性
* 学号
* 姓名
* 年龄
* 信息
* 方法
* 展示
*/
public class Student {
// 属性
String stuNo;
String name;
// 私有的属性,只能在当前类中使用
private int age;
String info;
/**
* 读取数据
* @return
*/
public int getAge() {
return age;
}
/**
* 设置数据
* @param age
*/
public void setAge(int age) {
// 过滤非法数据
if (age>0 && age<130) {
this.age = age;
} else {
System.err.println("非法年龄:" + age);
this.age = -1; // 尝试设置非法的年龄,把年龄设置为-1
}
}
public void show() {
System.out.println("Student [stuNo=" + stuNo + ", name=" + name + ", age=" + age + ", info=" + info + "]");
}
}
```
#### TestStudent
```
package com.shine.private0;
public class TestStudent {
public static void main(String[] args) {
// 创建对象
Student stu = new Student();
// 属性赋值
stu.stuNo = "20191012066";
stu.name = "张三";
//stu.age = 22; // 私有的属性不能再类的外部直接访问
stu.info = "法外狂徒";
stu.setAge(22);
System.out.println(stu.getAge());
// 调用方法展示信息
stu.show();
// 修改属性
//stu.age = 233;
stu.setAge(233);
stu.show();
}
}
```
#### Phone
```
package com.shine.private0;
public class Phone {
// 属性
private String brand;
private String model;
private String color;
private double price;
private String info;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
String[] brands = {"苹果","三星","华为","中兴","联想","摩托罗拉"};
this.brand = "不存在";
for (int i = 0; i < brands.length; i++) {
if (brand.equals(brands[i])) {
this.brand = brand;
break;
}
}
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
if (price>0 && price<1000000) {
this.price = price;
} else {
this.price = -1;
}
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
```
## 二、继承
### 2.1 概述
#### 生活中的继承
- 后辈从先辈那里继承得到财、物
- 后辈从先辈获取基因
#### 程序中的继承
- 子类获取到父类中的属性和方法
### 2.2 继承语法
```
class A{}
class B extends A{}
class C extends B{}
B能得到A中的属性和方法
C得到A和B中的属性和方法
Java是单继承,Java支持多级继承
```
### 2.3 继承入门案例
- 动物世界
```
package com.shine.extends0;
public class Demo01 {
public static void main(String[] args) {
/**
* 编写代码展示动物世界中的动物
*/
// 创建对象
Lion lion = new Lion();
Ratel ratel = new Ratel();
TheHyena hyena = new TheHyena();
}
}
/**
* 狮子类
*/
class Lion{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void hunt() {
}
}
/**
* 羊驼
*/
class Alpaca{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void climbTree() {
}
public void run() {
}
}
/**
* 鳄鱼
*/
class Crocodile {
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void swim() {
}
public void climb() {
}
}
/**
* 蓝鹤
*/
class BlueCrane{
String breed;
String name;
int age;
String sex;
String color;
String weight;
double height;
double length;
public void eat() {
}
public void sleep() {
}
public void fly() {
}
}
/**
* 所有动物中抽取共性的属性和方法,形成Animal这个类
*/
class Animal {
String breed;
String name;
int age;
String sex;
String color;
String weight;
double length;
public void eat() {
}
public void sleep() {
}
}
class Ratel {
}
class TheHyena extends Animal{
double height;
public void hunt() {
}
public void run() {
}
}
```
### 2.4 继承案例
#### Worker
```
package com.shine.extends0;
/**
* 类名
* 工人
* 属性
* 种类
* 姓名
* 年龄
* 工资
* 信息
* 方法
* 吃饭
* 睡觉
* 工作
*/
public class Worker {
String type;
String name;
int age;
double salary;
String info;
public void eat() {
System.out.println("工人需要吃饭");
}
public void sleep() {
System.out.println("工人需要睡觉");
}
public void work() {
System.out.println("工人需要工作");
}
}
```
#### Cook
```
package com.shine.extends0;
/**
* 类名
* 厨师
* 继承Worker,得到属性和方法
*/
public class Cook extends Worker{
// 属性
// 方法
public void cook() {
System.out.println("厨师做饭");
}
public void teastFood() {
System.out.println("厨师需要试菜");
}
}
```
### 2.5 不可继承
#### 父类中的构造方法
- 构造方法只负责本类类型对象的创建
#### 父类中私有的属性和方法
- 受访问权限修饰符限制,访问范围只能在当前类中
## 三、访问修饰符
### 3.1 概述
- 修饰属性、方法、类的修饰符
- 限制数据在不同位置的可见性
### 3.2 修饰符和范围
### 3.3 案例代码
#### modify01.FFF
```
package com.shine.modify01;
public class FFF {
public String publicStr = "publicStr";
protected String protectedStr = "protectedStr";
String defaultStr = "defaultStr";
private String privateStr = "privateStr";
/**
* 在同类中能访问的内容:
* public
* protected
* default
* private
*/
public void show() {
System.out.println(publicStr);
System.out.println(protectedStr);
System.out.println(defaultStr);
System.out.println(privateStr);
}
}
```
#### modify01.Demo01
```
package com.shine.modify01;
public class Demo01 {
public static void main(String[] args) {
/**
* public
* protected
* default
* private
*/
// 创建对象
FFF fff = new FFF();
/**
* 同一个包中能访问:
* public
* protected
* default
*/
System.out.println(fff.publicStr);
System.out.println(fff.protectedStr);
System.out.println(fff.defaultStr);
// System.out.println(fff.privateStr);
}
}
```
#### modify02.SSS
```
package com.shine.modify02;
import com.shine.modify01.FFF;
/**
* FFF的子类
*/
public class SSS extends FFF {
/**
* 在不同包子类中能访问的内容:
* public
* protected
*/
public void show() {
System.out.println(publicStr);
System.out.println(protectedStr);
// System.out.println(defaultStr);
// System.out.println(privateStr);
}
}
```
#### modify02.Demo02
```
package com.shine.modify02;
import com.shine.modify01.FFF;
public class Demo02 {
public static void main(String[] args) {
// 创建对象
FFF fff = new FFF();
/**
* 同其他位置能访问:
* public
*/
System.out.println(fff.publicStr);
// System.out.println(fff.protectedStr);
// System.out.println(fff.defaultStr);
// System.out.println(fff.privateStr);
}
}
```
## 四、方法重写
### 4.1 概述
- 子类从父类中继承得到的方法不一定能满足需求
- 可以在子类中定义和父类中【几乎】相同的方法:
- 方法的声明部分相同
- 方法体不同,可以根据子类需要重写方法体
### 4.2 重写注意事项
- 重写可以使用override标注
- 重写的方法参数列表、返回值类型必须和父类中相同
- 重写方法的访问修饰符范围要大于等于父类方法的修饰符
- 优先使用被重写的方法
### 4.3 代码
#### Worker
```
package com.shine.override;
/**
* 类名
* 工人
* 方法
* 工作
*/
public class Worker {
void work() {
System.out.println("工人需要工作");
}
}
```
#### Cook
```
package com.shine.override;
/**
* 类名
* 厨师
* 继承Worker,得到属性和方法
*/
public class Cook extends Worker{
@Override
void work() {
System.out.println("厨师的工作是切墩和颠勺");
}
}
```
#### Driver
```
package com.shine.override;
/**
* 类名
* 司机
* 继承了Worker
*/
public class Driver extends Worker{
@Override
public void work() {
System.out.println("司机的工作是开车");
}
public void work(String info) {
System.out.println("司机的工作是" + info);
}
}
```
#### TestWorker
```
package com.shine.override;
public class TestWorker {
public static void main(String[] args) {
// 工人对象
Worker worker = new Worker();
worker.work();
// 厨师对象
Cook cook = new Cook();
// 使用子类重写之后的方法
cook.work();
// 司机对象
Driver driver = new Driver();
// 使用子类重写之后的方法
driver.work();
}
}
```
## 五、super
### 5.1 概述
- 如果子类中存在和父类中重名的属性和方法
- 子类中的属性和方法会屏蔽父类中的属性和方法
- 如果明确表示调用父类中的属性和方法?
- 使用super来明确表示调用父类中的内容
### 5.2 super的使用
#### 调用父类中的属性
```
super.属性
```
#### 调用父类中的方法
```
super.方法(参数)
```
#### 调用父类中的构造器
```
super(参数)
```
#### 父类
```
package com.shine.super0;
public class WeChatV1 {
String name;
String info;
String version = "Version 1.0";
public WeChatV1() {
super();
}
public WeChatV1(String name, String info, String version) {
super();
this.name = name;
this.info = info;
this.version = version;
}
public void chat() {
System.out.println("微信第一版,能使用流量发送免费文字信息");
}
}
```
#### 子类
```
package com.shine.super0;
public class WeChatV2 extends WeChatV1{
String version = "Version 2.0";
public WeChatV2() {
this("", "", "");
}
public WeChatV2(String name, String info, String version) {
super(name, info, version); // 调用父类中的构造方法,必须放在构造方法的第一行
}
@Override
public void chat() {
super.chat(); // 调用父类中的实例方法
System.out.println("微信第2版,能发送图片和语音消息");
}
public void show() {
// 输出子类和父类中的属性
String version = "Version 2.1";
System.out.println(version); // 局部变量
System.out.println(this.version); // 实例变量
System.out.println(super.version); // 父类中的实例变量
}
}
```
#### 测试
```
package com.shine.super0;
public class Demo01 {
public static void main(String[] args) {
/**
* 父类
* 属性
* 方法
* 构造器
* 子类
* 属性
* 方法
* 构造器
*/
WeChatV2 chatV2 = new WeChatV2();
chatV2.chat();
}
}
```
### 5.3 子类对象创建过程
- 创建子类对象之前需要先创建父类对象
- 有父类的属性和方法 + 子类的属性和方法,构成子类的对象
- 默认调用父类的无参数构造方法,可以省略调用的代码
### 5.4 super调用构造器
#### 调用无参数构造器
- 在创建子类对象过程中默认调用父类中的无参数构造方法
#### 调用有参数构造器
- 如果父类中没有无参数构造方法,子类必须显示调