一、构造函数
1、从现实中抽象出类分为三步:
- 给具有共性特征的物体分类
- 找出它的属性
- 找出它的行为
2、使用类图描述类
- 用于分析和设计“类”
- 直观、容易理解
3、对象初始化
overload:一个类中有多个方法,同名不同参,此为overload(重载)。
在Dog.java中输入如下代码:
如果没有名字传入的时候,小狗的名字默认为Steve。然后我们写两个函数,一个是游泳,一个是玩碟子。
public class Dog {
public String name;
public String color;
public double age;
public int health;
/**默认构造函数
* 特点:1.构造函数的名字与类名必须一致
* 2.构造函数不能有返回值
* 3.无参构造函数,为默认方法
*/
public Dog() {
name = "Steve"; //作用:设置默认值
}
public void swim() {
System.out.println(name + " is swimming.");
}
public void playDisc() {
System.out.println(name + " is playing disc.");
}
}
然后,我们在GameUi.java文件中传入两只小狗的信息:
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog();
Dog d2 = new Dog();
d1.name = "Annie";
d1.color = "White";
d2.name = "Blake";
d2.color = "Black";
d1.playDisc();
d2.swim();
}
}
点击运行,得到下面的结果:
Annie is playing disc.
Blake is swimming.
我们也可以使用有参函数。 在同样一块作用域中,局部变量优先于成员变量。
在Dog.java中我们写入:
public class Dog {
public String name;
public String color;
public double age;
public int health;
public Dog(String name) {
this.name = name; //this指当前对象
this.health = 70; //健康值默认70
this.color = "Black"; //默认黑色
}
public void swim() {
System.out.println(name + " is swimming. ");
}
public void playDisc() {
System.out.println(name + " is playing disc.");
}
}
在GameUi.java中我们写入:
import com.icss.bk.biz.Dog;
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
Dog d2 = new Dog("Blake");
d1.name = "Annie";
d2.name = "Barron";
d2.color = "Yellow";
d1.playDisc();
System.out.println(d1.name + " is " + d1.color + ". Health status:" + " " + d1.health);
d2.swim();
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.health);
}
}
运行后我们得到结果:
Annie is playing disc.
Annie is Black. Health status: 70
Barron is swimming.
Barron is Yellow. Health status: 70
我们可以尝试写多参函数:
二、封装
面向对象(OOP):Object Orient Program
三个重要特征:继承、封装和多态。
封装:主要作用是为了代码安全。使用关键字private
,在作用域外不可被调用。
现在我们给小狗加上泳姿:
public class Dog {
public String name;
public String color;
public double age;
public int health;
private String swimType; //泳姿
public Dog(String name) {
this.name = name; //this指当前对象
this.health = 70; //健康值默认70
this.color = "Black"; //默认黑色
this.swimType = "Doggie style";
}
public void swim() {
System.out.println(name + " is swimming, using " + this.swimType + ".");
}
}
import com.icss.bk.biz.Dog;
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
Dog d2 = new Dog("Blake");
d2.name = "Barron";
d2.color = "Yellow";
d2.swim();
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.health);
}
}
得到结果:
Barron is swimming, using Doggie style.
Barron is Yellow. Health status: 70
假如我们想在GameUi.java中调用swimTpye,是无法调用和改变的。
如果改变的话,需要回到Dog.java函数中去修改。假如我们根据水的深浅,来修改小狗的游泳姿势。
首先,我们新建一个包,其中,entity的意思为实体包。
实体:只有属性,没有方法。
然后,我们建一个实体类,游泳池:
package com.iscc.bk.entity;
public class Pool {
public double length; //游泳池长度
public double width; //游泳池宽度
public double depth; //游泳池高度
public Pool(double length,double width,double depth) {
this.length = length;
this.width = width;
this.depth = depth;
}
}
然后,我们给小狗定义一下,如果游泳池水深超过2米,则使用潜水的方式:
package com.icss.bk.biz;
import com.iscc.bk.entity.Pool;
public class Dog {
public String name;
public String color;
public double age;
public int health;
private String swimType; //泳姿
public Dog(String name) {
this.name = name; //this指当前对象
this.health = 70; //健康值默认70
this.color = "Black"; //默认黑色
this.swimType = "doggie style";
}
public void swim(Pool pool) {
if(pool != null) {
if(pool.depth > 2) {
this.swimType = "diving";
}
System.out.println(name + " is swimming, using " + this.swimType + ".");
}
}
public void playDisc() {
System.out.println(name + " is playing disc.");
}
}
在Game.java界面,输入代码:
package com.icss.ui;
import com.icss.bk.biz.Dog;
import com.iscc.bk.entity.Pool;
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
Dog d2 = new Dog("Blake");
Pool pool = new Pool(100,25,3);
d1.name = "Annie";
d2.name = "Barron";
d2.color = "Yellow";
//d1.playDisc();
//System.out.println(d1.name + " is " + d1.color + ". Health status:" + " " + d1.health);
d2.swim(pool);
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.health);
}
}
运行后,得到结果:
Barron is swimming, using diving.
Barron is Yellow. Health status: 70
接下来,我们对健康值进行一些调整。我们可以限定,如果健康值输入为负数,或者大于100,都属于无效值。即设定范围为0道100之间。
首先,我们将health的属性由public
变为private
,然后进行一次封装。鼠标右键选择Source下的Generate Getters and Setters,勾选health。
我们会发现,下面多了2个方法。
在GameUi中,我们修改部分代码内容:
然后我们处理健康值不在0-100范围内的问题。
package com.icss.bk.biz;
import com.iscc.bk.entity.Pool;
public class Dog {
public String name;
public String color;
public double age;
private int health;
private String swimType; //泳姿,私有成员
public Dog(String name) {
this.name = name; //this指当前对象
this.health = 70; //健康值默认70
this.color = "Black"; //默认黑色
this.swimType = "doggie style";
}
public int getHealth() {
if(health > 100) {
this.health = 70; //将大于100的数调回70
}
else if(health < 0) {
this.health = 60; //将小于100的数调回60
}
else {
this.health = health; //正常赋值
}
return health;
}
public void setHealth(int health) {
this.health = health;
}
public void swim(Pool pool) {
if(pool != null) {
if(pool.depth > 2) {
this.swimType = "diving";
}
System.out.println(name + " is swimming, using " + this.swimType + ".");
}
}
public void playDisc() {
System.out.println(name + " is playing disc.");
}
}
然后我们把小狗的健康值调至范围以外
package com.icss.ui;
import com.icss.bk.biz.Dog;
import com.iscc.bk.entity.Pool;
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
d1.setHealth(-80);
Dog d2 = new Dog("Blake");
d2.setHealth(120);
Pool pool = new Pool(100,25,3);
d1.name = "Annie";
d2.name = "Barron";
d2.color = "Yellow";
d1.playDisc();
System.out.println(d1.name + " is " + d1.color + ". Health status:" + " " + d1.getHealth());
d2.swim(pool);
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.getHealth());
}
}
运行后,我们得到结果:
Annie is playing disc.
Annie is Black. Health status: 60
Barron is swimming, using diving.
Barron is Yellow. Health status: 70
使用同样的方法,可以对name、color、age等进行封装。
三、常量
接下来,我们给小狗确定性别
然后,鼠标右键选择Source下的Generate Getters and Setters,勾选sex
接下来,为小狗赋性别
最后,我们在游泳函数中假如小狗的性别
现在,我们运行程序得到结果:
Barron: male
Barron is swimming, using diving.
Barron is Yellow. Health status: 70
为了避免多次输入male和female出现错误,我们可以这么操作
public class GameUi {
public static final String MALE = "male";
public static final String FEMALE = "female";
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
d1.setHealth(-80);
d1.setSex(FEMALE);
Dog d2 = new Dog("Blake");
d2.setHealth(120);
d2.setSex(MALE);
Pool pool = new Pool(100,25,3);
d1.name = "Annie";
d2.name = "Barron";
d2.color = "Yellow";
d1.swim(pool);
System.out.println(d1.name + " is " + d1.color + ". Health status:" + " " + d1.getHealth());
d2.swim(pool);
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.getHealth());
}
}
输出得到结果:
Annie: male
Annie is swimming, using diving.
Annie is Black. Health status: 60
Barron: female
Barron is swimming, using diving.
Barron is Yellow. Health status: 70
上面的例子中,MALE
和FEMALE
就是常量。当然,我们还要考虑代码摆放的位置,因为放在GameUi中,在Dog中就无法调用了,因此,需要将常量封装到entity里面。我们在entity包中新建Sex类,然后将之前的两行代码从GameUi中转移至Sex中
package com.iscc.bk.entity;
public class Sex {
public static final String MALE = "male";
public static final String FEMALE = "female";
}
然后在GameUi调用的时候,我们也需要将代码进行调整
public class GameUi {
public static void main(String[] args) {
Dog d1 = new Dog("Annie");
d1.setHealth(-80);
d1.setSex(Sex.FEMALE);
Dog d2 = new Dog("Blake");
d2.setHealth(120);
d2.setSex(Sex.FEMALE);
Pool pool = new Pool(100,25,3);
d1.name = "Annie";
d2.name = "Barron";
d2.color = "Yellow";
d1.swim(pool);
System.out.println(d1.name + " is " + d1.color + ". Health status:" + " " + d1.getHealth());
d2.swim(pool);
System.out.println(d2.name + " is " + d2.color + ". Health status:" + " " + d2.getHealth());
}
}
运行后,结果和之前一致。