JAVA学习:抽象与封装

本文介绍了JAVA中的类抽象过程,包括如何从现实抽象出类,使用类图描述,以及对象初始化。接着讲解了封装的概念,通过示例展示了如何使用封装保护代码安全,如限制对属性的直接访问。最后讨论了常量的使用,如何创建和应用常量以避免错误输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、构造函数

1、从现实中抽象出类分为三步:

  1. 给具有共性特征的物体分类
  2. 找出它的属性
  3. 找出它的行为

2、使用类图描述类

  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

上面的例子中,MALEFEMALE就是常量。当然,我们还要考虑代码摆放的位置,因为放在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());
	}

}

运行后,结果和之前一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值