封装与继承

为何使用封装
读懂别人的代码也是程序员必备的技能之一
案例中的代码有什么缺陷?
Penguin p =new
Penguin();
p.health=-100;
以上代码中属性随意访问,有着不合理的赋值
流程控制(选择结构,循环结构等)必须要在方法中写!!
这时就需要用到封装
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问,这就叫做封装
封装的两大原则
把所有的属性藏起来
把尽可能多的东西藏起来,对外提供便捷的**’‘接口’’**
封装
将类的某些信息(属性)隐藏在类内部,不允许外部程序直接访问
通过该类提供的方法来实现对隐藏信息的操作和访问
面向对象的三大特征之一
实现封装

在前面加private 私有的,其他人访问不到
对电子宠物属性封装后输出
宠物狗狗类
/**
* 宠物狗狗类
*/
public class Dog {
private String name = "无名氏"; // 昵称,默认值是"无名氏"
//1.health属性不被用户访问到 2.程序编写过程中要能控制health的赋值--方法中
//1.隐藏属性 int前加private
private int health =100; // 健康值,默认值是100,健康值在0-100之间,小于60为不健康
private int love = 0; // 亲密度
private String strain = "聪明的拉布拉多犬"; // 品种
//2.添加属性的setter(设置)/getter(获取)方法,并加入属性控制语句
//以set为前缀后面写隐藏起来的变量名字
//set是设置方法
//setter:属性赋值,属性的操作(正确的判断筛选等)
public void setHealth(int health) {
if(health<0 ||health>100){
System.out.println("宠物的健康值只能在0-100之间!");
this.health = 60;
//return跳转出去
return;
}else{
//方法间直接调用
this.health = health;
}
}
//getter:属性取值
//获取health属性
public int getHealth(){
return this.health;
}
public void setName(String name) {
this.name=name;
}
public String getName() {
return this.name;
}
public void setLove(int love) {
this.love=love;
}
public int getLove() {
return this.love;
}
public void setStrain(String strain) {
this.strain=strain;
}
public String getStrain () {
return this.strain;
}
/**
* 输出狗狗的信息
*/
public void print() {
System.out.println("宠物的自白:\n我的名字叫" + this.name +
",健康值是" + this.health + ",和主人的亲密度是"
+ this.love + ",我是一只 " + this.strain + "。");
}
}
输出
public class TestPet {
public static void main(String[] args) {
Dog dog = new Dog();
// 直接输出getHealth方法就可以
// 这样的好处是health只能通过我想要的方法来输出
dog.setHealth(500);
System.out.println(dog.getHealth());
/*
* 伪代码 do{ dog.health=-1000; System.out.println("...."); }while(dog.health<0 ||
* dog.health>100);
*/
dog.setLove(3);
System.out.println(dog.getLove());
dog.setName("多多");
System.out.println(dog.getName());
dog.setStrain("吉娃娃");
System.out.println(dog.getStrain());
dog.print();
}
}
封装的好处
便于使用者正确使用系统,防止错误修改属性,使每个步骤变成了一个独立的小部分提高了系统的独立性
有助于系统之间的松耦合,提高系统的独立性
(耦合:程序严重依赖,粘连在一起)
提高了软件的可重用性
降低了构建大型系统的风险
封装如何实现
属性-private
添加对应setter(设置)/getter(获取)
对属性合法值进行判断
封装应用练习
包
本节目标
理解包的作用
掌握如何创建包
掌握如何声明及导入包
会使用包管理类
提问:如何有两个同名的类而不冲突

windows解决问题的机制放到其他文件夹中就可以解决同名冲突问题.
包:
允许类组成较小的单元(类似文件夹),易于找到和使用相应的文件
防止命名冲突区分名字相同的类
有助于实施访问权限控制
包命名的方法:
包名由小写字母组成,不拿以圆点开头或结尾
包名用 . 分隔
包名之前最好加上唯一的前缀,通常使用组织倒置的网络域名
包名后续部分依不同机构内部的规范不同而不同
package.cn.jbit.inherit;
public class School{
}
声明包的语句要必须写在源代码的最顶部,源代码的第一条语句,用package声明包,必须以分号结尾
为了使用不在同一包中的类,需要在java程序中使用import这个关键字导入这个类
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BNYYJYWB-1635326490808)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211026171808373.png)]](https://img-blog.csdnimg.cn/c49dba7e0ba744679fd0ee4c397ba9d5.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5LuO6Zu25byA5aeL55qEamF2YeS7o-eggeeUn-a0uw==,size_11,color_FFFFFF,t_70,g_se,x_16)
一个类同时引用了两个来自不同包的同名类
必须通过完整类名来区分
每个包都是独立的,顶层的包不会包含子包的类
package和import的顺序是固定的
1.package必须位于第一行(不包括注释行)
2.只允许有一个package语句
3.其次是import
4.接着是类的声明

访问权限控制

访问权限控制
类的访问控制
类成员的访问控制:属性 方法
类的访问修饰符
public修饰符:公有访问级别
package cn.com.opp1;
//类可以通过public修饰符修饰
public class Person{
}
默认修饰符:包级私有访问级别
package cn.com.opp1;
//类可以通过public修饰符修饰
class Person{
}
在同包的测试类可以访问public修饰的类,也可以访问默认修饰符修饰的类
但是,不同包的类只可以访问public修饰的类,不可用访问默认修饰符修饰的类

其他的类中不拿调用类中private修饰的类成员(属性与方法)
默认修饰符修饰的类成员,本类可以访问
static变量
static可以用来修饰
成员变量
静态变量,static修饰后不需要创建对象可以直接通过类名访问
成员方法
静态方法,static修饰后不需要创建对象可以直接通过类名访问
代码块
静态代码块,当Java虚拟机加载类时,就会执行该代码块
person类
public class Person {
// 属性:成员变量,全局变量
int age;
String email;
String name;
}
测试类
public static void main(String[] args) {
//调用类的成员变量(属性),创建对象(实例),通过对象去访问
Person p = new Person();
p.age=18;
p.email="987987@qq.com";
p.name="冯小洲";
}
经过static修饰email后
person类
int age;
String name;
//静态变量
static String email;
测试类
public static void main(String[] args) {
//调用类的成员变量(属性),创建对象,通过对象去访问
Person p = new Person();
p.age=18;
p.name="冯小洲";
//静态变量
Person.email="987987@qq.com";
}
类的成员变量包括
类变量(静态变量)
被static修饰的变量
在内存中只有***一个***拷贝(在内存中)
类内部,可以在任何方法内直接访问静态变量
其他类中,可以直接通过类名访问
实例变量
实例变量
没有被static所修饰的变量
每创建一个实例,就会为实例变量分配一次内存,实例变量可以在内存中有多个拷贝,互不影响
要通过实例(对象)去访问

static静态的变量不会变化,上面无论是st1还是st2,都是在操作初始的int num,因为默认值为0,所以他们输出的都是依次++,

这四句操作的num都是同一个num
虽然用上方的实例方法不报错,但是还是要用静态方式类名调用去写: 类名.变量名=赋值;
static变量的作用:
1.能被类的所有实例所共享,可作为势力之间进行交流的共享数据
2.如果类的所有实例都包含一个相同的常量属性,可把这个属性定义为静态常量类型,从而节省内存空间

先分析需要什么属性什么方法,需要什么样的属性什么样的方法,再去开始写代码
分析:
1.投票总数到达100时,停止投票
static final MAX;
总投票数
static amount
选民投票类
package homework;
public class Work1_Voter {
//模拟选民投票过程:一群选民进行投票,每个选民秩序投一次票,并且投票总数达到100时停止投票
private String name ;
//添加一个带参的构造方法
public Work1_Voter(String name) {
this.name=name;
}
public void setName() {
}
public String getName(String name) {
return name;
}
//当前的投票数
static int amount ;
//最终的投票数,写一个常量100,如果到最大值max100就结束
static final int MAX=100;
//写投票时的方法
public void vote() {
if(amount ==MAX) {
System.out.println("投票总数已经达到100,停止投票");
return;
}else {
amount++;
System.out.println(this.name+"您已经投票成功!!当前票数为:"+amount);
}
}
}
输出测试类
package homework;
public class Work1 {
public static void main(String[] args) {
for (int i = 1; i <= 105; i++) {
Work1_Voter voter = new Work1_Voter("第" + i + "个人投票完毕");
voter.vote();
}
}
}
static变量
类变量
在内存中只有一个拷贝
类内部,可以在任何方法内直接访问静态变量
其他类中可以直接通过类名访问类成员的访问控制
能被类的所有实例共享,可作为实例之间进行交流的共享数据
static方法
静态方法:可以直接通过类名访问
Person.m3();
静态方法中不能使用this 和super
不拿直接访问类中所述的类的实例变量和实例方法
可直接访问类中的静态变量和静态方法
实例方法:通过实例访问
可直接访问所属类的静态变量.静态方法.实例变量和实例方法
静态方法必须被实现
main()方法就是最常用的静态方法
Math.random();就是引用了Math类中的random静态方法
static代码块

static int num =100;
//?静态代码块
static{
num+=10;
System.out.println(num);
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9UC205ua-1635326490818)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211027164540927.png)]](https://img-blog.csdnimg.cn/8ba7ed246b4848eaa9268f50c24dcbcb.png)
继承

将重复相同的代码抽取到父类中
子类继承他所有的属性和方法,使用继承能优化设计
如何编写继承的父类与子类

继承是Java中实现代码重用的重要手段之一.Java中只支持单根继承,即一个类只能有一个直接父类

理解继承
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4t4eiJe4-1635326490822)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211027171031911.png)]](https://img-blog.csdnimg.cn/3b9d28fccc8b4f2baf33acf5390a34da.png)
子类能从父类中继承什么???
1.public修饰的所有属性和方法,protected修饰的所有属性和方法
2.默认修饰符修饰的属性和方法,但是子类和弗雷必须要在哦那个一个包内.
