上节我们简单的对面向对象编程中的对象和类做了说明,本节我们来说说Java面向对象的三大特性。
在上一节中,我们无论是哈士奇类、波斯猫类,还是我们的哺乳动物公共类,其中的属性都是以private
修饰符开头的,而方法我们是以public
修饰符开头的,其二者区别在于private
修饰符所描述的属性和方法只能在本类内部调用,而public
修饰符具有最大的访问权限,可以访问任何一个在CLASSPATH下的类、接口、异常等。上一节的哈士奇类、波斯猫类、以及哺乳动物公共类都使用了Java面向对象三大特性中的封装思想。
封装是将对象的属性和方法相结合,通过方法将对象的属性和实现细节保护起来,实现对象的属性隐藏。封装特性的核心思想是“隐藏细节”、“数据安全”。封装的好处有很多,比如降低耦合度、类内部结构可以自由修改、可以对成员变量进行更精确的控制、隐藏信息,实现细节。
使用封装是为了将实体共有特性进行封装,减少各类中出现的重复性代码,同时也为了修改降低难度以及出错率。比如我们在上一节中写的哈士奇类和波斯猫类,如果我们还需要设计藏獒、牧羊犬、贵宾犬等等狗类动物的对象,若我们直接将哈士奇类复制粘贴后修改其中的该狗所具备的特殊行为,那么我们将修改同样的属性和方法时,我们就需要对所有的类进行修改,若在修改中出现错误时,那么整个程序都会出现Bug。而我们使用了封装后,我们将这些狗类中共有的特性封装成一个Dog类,我们需要修改它们共性的属性方法时,我们只需要修改Dog类中的属性和方法。它们各自的类继承自Dog公共类,我们只需要在子类中实现它们的特性行为或特性状态即可,修改时只需要修改子类即可,不影响其他子类的实现。
package com.ohayoi;
/**
* 公共狗类
* @author ohayoi
*/
public class DogClaz {
private String name;//种类
private String color;//毛色
private double weight;//体重
private double height;//身高
/**
* 构造函数,用于构建特定属性的狗种类
* 可以根据需要的不同属性来设定构造函数,
* 若不重写构造函数,则使用默认不带参数的构造函数
* @param name
* @param age
* @param color
* @param weight
* @param height
*/
public DogClaz(String name) {
super();
this.name = name;
}
public DogClaz(String name, String color, double weight, double height) {
super();
this.name = name;
this.color = color;
this.weight = weight;
this.height = height;
}
public void sleep() {
System.out.println("我来自" + getName() + "家族,我已经睡着了~");
}
public void jump() {
System.out.println("我来自" + getName() + "家族,我能够跳很高~");
}
public void weight() {
System.out.println("我来自" + getName() + "家族,最近吃的有点多,该减肥了~");
}
/*
* getter & setter
* getter 对外接口,用户获取相关属性设置
* setter 对外接口,用户设置相关属性
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
package com.ohayoi;
/**
* 哈士奇
* @author ohayoi
*/
public class Husky extends DogClaz{
private int age;//年龄
/**
* 重写父类构造函数,设置具体的狗类,加入年龄
* @param name
* @param age
*/
public Husky(String name, int age) {
super(name);
this.age = age;
}
@Override
public void sleep() {
System.out.println("我是" + getName() + ",我已经睡着了~");
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.ohayoi;
public class TestDemo {
public static void main(String[] args) {
DogClaz dc = new DogClaz("哈士奇");
dc.jump();
Husky h = new Husky("二哈", 10);
h.sleep();
}
}
//结果
我来自哈士奇家族,我能够跳很高~
我是二哈,我已经睡着了~
在上面代码中我们提到了两个重要的概念,一是构造函数,其用于类的初始化,构造函数可以是有参数的,也可以是无参数的。若不重写构造函数,那么将使用Java默认的构造函数,其是无参的。若重写构造函数,将不能使用默认的无参构造函数,若需要使用无参的构造函数时,需要将其重写。另一个是方法重载,其提供了可以创建多个重名的方法,但其中的参数个数、类型都不可相同。如我们DogClaz中对构造函数的重载,两个构造函数一个是全属性构造函数,一个是仅有品种的构造函数。
网友评论