学习java的第十二课——封装与继承

封装与继承

在这里插入图片描述

为何使用封装

读懂别人的代码也是程序员必备的技能之一

案例中的代码有什么缺陷?

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)]

一个类同时引用了两个来自不同包的同名类

​ 必须通过完整类名来区分

每个包都是独立的,顶层的包不会包含子包的类

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;

  1. 总投票数

    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)]

继承

在这里插入图片描述

将重复相同的代码抽取到父类中

子类继承他所有的属性和方法,使用继承能优化设计
在这里插入图片描述

如何编写继承的父类与子类

在这里插入图片描述

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

在这里插入图片描述

理解继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4t4eiJe4-1635326490822)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211027171031911.png)]

子类能从父类中继承什么???

​ 1.public修饰的所有属性和方法,protected修饰的所有属性和方法

​ 2.默认修饰符修饰的属性和方法,但是子类和弗雷必须要在哦那个一个包内.

在这里插入图片描述


版权声明:本文为redredredr21原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。