第1关:什么是封装,如何使用封装
相关知识
为了完成本关任务,你需要掌握:1.什么是封装;2.封装的意义;3.实现Java封装的步骤。
什么是封装
封装:就是隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装时的权限控制符区别如下:
封装的意义
对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有四大好处:
良好的封装能够减少耦合。
类内部的结构可以自由修改。
可以对成员进行更精确的控制。
隐藏信息,实现细节。
封装把一个对象的属性私有化,同时提供一些可以被外界访问属性的方法,如果不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
实现Java封装的步骤
修改属性的可见性来限制对属性的访问(一般限制为private),例如:
public class Person {
private String name;
private int age;
}
这段代码中,将 name 和 age 属性设置为私有的,只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,例如:
/*
*封装演示
*/
public class Person {
/*
* 对属性的封装 一个人的姓名、性别和年龄都是这个人的私有属性
*/
private String name;
private String sex;
private int age;
/*
* setter()、getter()是该对象对外开放的接口
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
封装可以使我们容易地修改类的内部实现,而无需修改使用了该类的客户代码,就可以对成员变量进行更精确的控制。
public void setAge(int age) {
if (age > 120) {
System.out.println("ERROR:error age input...."); // 提示错误信息
} else {
this.age = age;
}
}
public String getSexName() {
if ("0".equals(sex)) {
sexName = "女";
} else if ("1".equals(sex)) {
sexName = "男";
} else {
sexName = "人妖";
}
return sexName;
}
编程要求
根据提示,在右侧编辑器Begin-End处补充代码:
声明一个Person类,私有化属性name和age,并将字段封装起来;
在Person类中定义一个talk()方法,打印姓名和年龄信息;
在main方法中声明并实例化一Person对象p,给p中的属性赋值,调用talk()方法打印 我是:张三,今年:18岁。
测试说明
测试输入: 无
预期输出:
我是:张三,今年:18岁
代码展示
package case1;
public class TestPersonDemo {
public static void main(String[] args) {
/********* begin *********/
// 声明并实例化一Person对象p
Person p=new Person();
// 给p中的属性赋值
p.setName("张三");
p.setAge(18);
// 调用Person类中的talk()方法
p.talk();
/********* end *********/
}
}
// 在这里定义Person类
class Person {
/********* begin *********/
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void talk(){
System.out.print("我是:"+name+",今年:"+age+"岁");
}
/********* end *********/
}
第2关:什么是继承,怎样使用继承
相关知识
为了完成本关任务,你需要掌握:1.继承的基本概念;2.继承的特性;3.子类对象的实例化过程。
继承的基本概念
所谓继承:是指可以让某个类型的对象获得另一个类型的对象的属性的方法。
兔子和羊属于食草动物类,狮子和豹属于食肉动物类。
食草动物和食肉动物又是属于动物类。
所以继承需要符合的关系是:is-a,父类更通用,子类更具体。
虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。
在讲解继承的基本概念之前,读者可以先想一想这样一个问题:现在假设有一个Person类,里面有name与age两个属性,而另外一个Student类,需要有name、age、school三个属性,如图所示,从这里可以发现Person中已经存在有name和age两个属性,所以不希望在Student类中再重新声明这两个属性,这个时候就需要考虑是不是可以将Person类中的内容继续保留到Student类中,也就是引出了接下来所要介绍的类的继承概念。
在这里希望Student类能够将 Person类的内容继承下来后继续使用:
Java类的继承,可用下面的语法来表示:
class 父类 // 定义父类
{
...
}
class 子类 extends 父类 // 用extends关键字实现类的继承
{
...
}
范例:
public class TestPersonStudentDemo {
public static void main(String[] args) {
Student s = new Student();
// 访问Person类中的name属性
s.name = "张三";
// 访问Person类中的age属性
s.age = 18;
// 访问Student类中的school属性
s.school = "哈佛大学";
System.out.println("姓名:" + s.name + ",年龄:" + s.age + ",学校:" + s.school);
}
}
class Person {
String name;
int age;
}
class Student extends Person {
String school;
}
输出结果:
姓名:张三,年龄:18,学校:哈佛大学
由上面的程序可以发现,在Student类中虽然并未定义name与age属性,但在程序外部却依然可以调用name或age,这是因为Student类直接继承自Person类,也就是说Student类直接继承了Person类中的属性,所以Student类的对象才可以访问到父类中的成员。
继承的特性
子类拥有父类非private的属性和方法;
子类可以拥有自己的属性和方法,即子类可以对父类进行扩展;
子类可以用自己的方式实现父类的方法;
在Java中只允许单继承,而不允许多重继承,也就是说一个子类只能有一个父类,但是Java中却允许多层继承,多层继承就是,例如类C继承类B,类B继承类A,所以按照关系就是类A是类B的父类,类B是类C的父类,这是Java继承区别于C++继承的一个特性;
提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
多重继承:
class A{
...
}
class B{
...
}
class C extends A,B{
...
}
由上面可以发现类C同时继承了类A与类B,也就是说类C同时继承了两个父类,这在Java中是不允许的。
多层继承:
class A{
...
}
class B extends A{
...
}