Day11(掌握)
一、封装概述
1.1 定义
- java语言最大的特点:面向对象
- 面向对象的特点
- 封装
- 继承
- 多态
- 为什么要封装
- 类中定义的属性很多,在创建对象之后我们可以随意获取和设置这些属性
- 有些属性的值符合语法定义,但是不符合生产需求和常识
- 需要把这个属性隐藏起来,不让外部随意访问,使用private对属性进行修饰
- 被private修饰的属性或者方法只能在类的内部访问到,外部无法访问,所以对于类外部的其他内容来讲属性变得不可见
- 可以在这个类的内部定义一组和属性相关的方法
- setter
- 设置属性的值
- 可自定义设置的规则
- getter
- 获取属性值
- 可以自定义获取的规则
- setter
- 未封装的代码
package com.qf.pri;
public class Demo01 {
public static void main(String[] args) {
Stu stu01 = new Stu();
stu01.name = "张三";
stu01.age = 23;
stu01.show();
Stu stu02 = new Stu();
stu02.name = "李思思";
// 年龄的范围符合语法,但是不符合生产需求
stu02.age = 2444;
stu02.show();
}
}
class Stu{
// 属性
String name;
int age;
String gender;
String addr;
// 方法
public void show() {
System.out.println("我的名字是" + name + ",我今年" + age);
}
}
- 封装之后的代码
package com.qf.pri;
public class Demo02 {
public static void main(String[] args) {
Student s01 = new Student();
s01.name = "王五";
s01.setAge(25);
s01.show();
}
}
class Student{
// 属性
String name;
// 私有化属性age
private int age;
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
// 方法
public void show() {
System.out.println("我的名字叫" + name + ",我今年" + age);
}
}
1.2 自定义set中的规则
- 在set方法中可以根据生产的需求,自己定义属性的设置规则
package com.qf.pri;
public class Demo03 {
public static void main(String[] args) {
Stus s01 = new Stus();
s01.name = "赵柳";
s01.setAge(26);
s01.show();
System.out.println("===============");
Stus s02 = new Stus();
s02.name = "田七";
s02.setAge(27777);
s02.show();
}
}
class Stus{
// 属性
String name;
// 私有化属性age
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
// 自定义设置参数的规则
if (age >= 16 && age <= 40) {
this.age = age;
} else {
// 错误参数的提示
System.err.println("年龄超出范围...");
this.age = -1;
}
}
// 方法
public void show() {
System.out.println("我的名字叫" + name + ",我今年" + age);
}
}
1.3 set和get方法被绕过的情况
- 我们创建对象的时候有可能是调用的有参数的构造方法
- 在构造方法中可以直接给属性完成赋值的操作
- 这样就绕过了set和get中自定义的规则
- 如果想要set和get中的规则继续生效的话,在构造方法中调用set和get方法
package com.qf.pri;
public class Demo04 {
public static void main(String[] args) {
Students s01 = new Students();
s01.name = "周毅";
s01.setAge(21);
s01.show();
System.out.println("===============");
Students s02 = new Students("吴二", 22);
s02.show();
System.out.println("===============");
Students s03 = new Students("正三", 2333);
s03.show();
}
}
class Students{
// 属性
String name;
private int age;
// 构造方法
public Students() {
super();
}
public Students(String name, int age) {
super();
// 构造方法可以逃过set和get方法直接给属性赋值
this.name = name;
// 如果想要set中的规则继续生效就在构造方法中调用set和get方法
this.setAge(age);
}
public int getAge() {
return age;
}
public void setAge(int age) {
System.out.println("setAge被调用啦啦啦啦啦");
if (age >= 16 && age <= 40) {
this.age = age;
}else {
this.age = -1;
System.err.println("年龄范围有误....");
}
}
// 方法
public void show() {
System.out.println("我是" + name + ",我今年" + age);
}
}
二、继承
2.1 定义
- 生活中的继承
- 有亲属关系的一些人从其他亲属那里获取到遗留在人世间的财、物
- 程序中的继承
- 子类从父类中获取父类的属性和方法
2.2 父类的抽取
- 从多个子类中提取出相同或者相近的属性、方法,放在一个类中,形成父类
- 子类通过关键字extends和这个类产生继承关系
- 子类和父类需要满足一个条件
- 子类 is a 父类
2.3 实现继承
- 语法
class 子类 extends 父类{
子类的代码
}
- 没有继承关系的代码
package com.qf.extend;
public class Demo01 {
public static void main(String[] args) {
}
}
/*
class Dog{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("狗子需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("狗子需要睡觉保持精力");
}
public void lookHome() {
System.out.println("狗子可以看家和拆家");
}
}
class Cat{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("猫咪需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("猫咪需要睡觉保持精力");
}
public void catchMouse() {
System.out.println("有的猫咪会抓老鼠");
}
}
class Bear{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("熊大需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("熊二需要睡觉保持精力");
}
public void protectForest() {
System.out.println("熊熊要保护森林");
}
}
*/
- 有继承关系的代码
package com.qf.extend;
public class Demo02 {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
dog.type = "哈士奇";
dog.eat();
dog.lookHome();
}
}
/**
* 动物类
* 抽取了Dog、Cat、Bear几个类中公共的属性和方法
* @author Dushine2008
*
*/
class Animal{
// 共有的属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 共有的方法
public void eat() {
System.out.println(type + "需要吃食物维持生命活动...");
}
public void sleep() {
System.out.println(type + "需要睡觉修复细胞...");
}
}
/**
* Dog类
* 继承了Animal
* 获取到了Animal属性和方法
* @author Dushine2008
*
*/
class Dog extends Animal{
public void lookHome() {
System.out.println("狗子可以看家和拆家");
}
}
/**
* Cat类
* 继承了Animal的属性和方法
* @author Dushine2008
*
*/
class Cat extends Animal{
public void catchMouse() {
System.out.println("有的猫咪会抓老鼠");
}
}
/**
* Bear类
* 继承了Animal,获取Animal的属性和方法
* @author Dushine2008
*
*/
class Bear extends Animal{
public void protectForest() {
System.out.println("熊熊要保护森林");
}
}
/*
class Dog{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("狗子需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("狗子需要睡觉保持精力");
}
public void lookHome() {
System.out.println("狗子可以看家和拆家");
}
}
class Cat{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("猫咪需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("猫咪需要睡觉保持精力");
}
public void catchMouse() {
System.out.println("有的猫咪会抓老鼠");
}
}
class Bear{
// 属性
String type;
String name;
int age;
String color;
int weight;
int height;
// 方法
public void eat() {
System.out.println("熊大需要吃食物维持生命活动");
}
public void sleep() {
System.out.println("熊二需要睡觉保持精力");
}
public void protectForest() {
System.out.println("熊熊要保护森林");
}
}
*/
三、java继承的特点
3.1 单继承
- java中的一个类只能有一个直接父类
- 但是父类还可以拥有父类…
- java支持单继承,可以多级继承,子类能获取到父类、祖父类中的所有属性和方法
package com.qf.extend;
public class Demo03 {
public static void main(String[] args) {
// CollegeStudent的对象可以调用父类,父类的父类...中的属性和方法
CollegeStudent cs = new CollegeStudent();
}
}
class Human{
// 属性
String type;
String faceValue;
String name;
String gender;
// 方法
public void eat() {
System.out.println("人需要进食维持生命活动...");
}
public void sleep() {
System.out.println("人需要睡觉保持精力...");
}
}
class Student extends Human{
// 特有的属性
String stuId;
String className;
// 特有的方法
public void study() {
System.out.println("学生,以学习为主的一群人...");
}
}
class CollegeStudent extends Student{
// 独有的特征
String field;
// 独有的方法
public void postgraduate() {
System.out.println("大学生可以选择考研...");
}
}
3.2 父类的构造方法
- 子类继承不到父类的构造方法
- 但是可以使用super调用父类的构造方法
3.3 父类私有的属性和方法
- 子类继承不到父类的私有属性和方法
- 因为语法规定:
- 私有修饰的属性和方法只能在本类中访问
package com.qf.extend;
public class Demo04 {
public static void main(String[] args) {
Stu s01 = new Stu();
}
}
class People{
// 属性
String name;
int age;
// 对本类的描述
private String desc = "这个是People类的描述信息";
public People() {
super();
}
public People(String name, int age, String desc) {
super();
this.name = name;
this.age = age;
this.desc = desc;
}
public void show() {
System.out.println("我是" + name + "我今年" + age);
}
// 私有的方法:展示自己的类信息
private void showInfo() {
System.out.println(desc);
}
}
class Stu extends People{
public void getDesc() {
System.out.println(name);
System.out.println(age);
// 子类无法获取父类私有的属性和方法
//System.out.println(desc);
}
}
四、访问修饰符
4.1 定义
种类 | 本类 | 本包其他类 | 其他包子类 | 其他位置 |
---|---|---|---|---|
private | √ | × | × | × |
default | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
4.3 编写代码验证访问范围
- 自己参考代码编写
五、方法重写
5.1 定义
- 子类在继承父类后可以获取父类中所有非私有的属性和普通方法
- 但是子类可能有自己独特的功能,继承过来的方法无法满足这些需求
- 但是子类的功能的名字还和父类一样,这样子类就可以对从父类继承过来的方法进行重写
- 定义
- 子类中出现类方法声明和父类中完全相同的头条
- 方法名字一样
- 参数列表一样
- 返回值类型一样
- 权限修饰符一样或者范围更大
5.2 案例
package com.qf.override;
public class Demo01 {
public static void main(String[] args) {
// 方法重写案例
WeChatV1 w01 = new WeChatV1();
w01.chat();
WeChatV2 w02 = new WeChatV2();
w02.chat();
WeChatV3 w03 = new WeChatV3();
w03.chat();
WeChatV4 w04 = new WeChatV4();
w04.chat();
}
}
class WeChatV1{
public void chat() {
System.out.println("微信第一版跨时代产品上市,能通过网络发消息,发消息免费.");
}
}
class WeChatV2 extends WeChatV1{
@Override
public void chat() {
System.out.println("微信第二版隆重上市,可以通过网络发送语音消息,每人每天可免费发出200条");
}
}
class WeChatV3 extends WeChatV2{
@Override
public void chat() {
System.out.println("微信第三版隆重上市,可以通过网络发起语音通话,通话时长无限制");
}
}
class WeChatV4 extends WeChatV3{
@Override
public void chat() {
System.out.println("微信第四版隆重上市,可以通过网络发起视频通话,通话时长无限制");
}
}
六、关键字super
6.1 定义
- 子类继承父类之后,可以获取父类所有非私有的普通属性和方法
- 如果发生对属性和方法的重写,子类再次使用的时候,全部是重写之后的结果
- 如果想调用父类中的属性和方法,需要借助关键字super
6.2 super调用属性和方法
- super.方法名(参数列表)
- 调用父类的方法
- super.属性名
- 调用父类的属性
package com.qf.override;
public class Demo02 {
public static void main(String[] args) {
F f = new F();
// f.printShape();
S s = new S();
s.printShape();
s.printStr();
}
}
class F{
String str = "父类中的属性str";
public void printShape() {
for (int i = 1; i < 10; i++) {
for (int j = 1; j <= i; j++) {
System.out.print(j + "*" + i + "=" + j*i + "\t");
}
System.out.println();
}
}
}
class S extends F{
String str = "子类中的str";
@Override
public void printShape() {
// 明确调用父类中的printShape方法
super.printShape();
System.out.println("==========================================================================");
}
public void printStr() {
// 子类的str覆盖了父类继承过来的str,输出的是子类自己的
System.out.println(str);
// 如果想调用父类的str,需要使用super关键字
System.out.println(super.str);
}
}
6.3 super调用父类的构造方法
- super(参数列表)
- 调用父类的构造方法
package com.qf.override;
public class Demo03 {
public static void main(String[] args) {
Animal a01 = new Animal("藏獒", "狗哥", 3, "雄性");
a01.show();
Dog dog = new Dog("吉娃娃", "狗弟", 3, "雄性");
dog.show();
}
}
class Animal{
// 属性
String type;
String name;
int age;
String gender;
public Animal() {
super();
}
public Animal(String type, String name, int age, String gender) {
super();
this.type = type;
this.name = name;
this.age = age;
this.gender = gender;
}
// 方法
public void show() {
System.out.println("Animal [type=" + type + ", name=" + name + ", age=" + age + ", gender=" + gender + "]");
}
}
class Dog extends Animal{
public Dog() {
super();
}
public Dog(String type, String name, int age, String gender) {
// 调用父类有参数的构造方法
super(type, name, age, gender);
}
}
6.4 this和super
- 调用属性
- this.属性
- 调用子类对自己的属性
- super.属性
- 调用父类的属性
- this.属性
- 调用方法
- this.方法名(参数列表)
- 调用子类自己的方法
- super.方法名(参数列表)
- 调用父类的方法
- this.方法名(参数列表)
- 调用构造方法
- this(参数列表)
- 调用子类自己的构造方法
- super(参数列表)
- 调用父类的构造方法
- 注意
- 在调用构造方法的时候,this和super不能同时存在
- 子类的构造方法中会默认调用父类空参的构造方法
- this(参数列表)