面向对象入门
基本概念
- 对象:①一切皆为对象;②每个对象都是唯一的;③对象都属于某个类;④对象都有属性和行为。
- 类:类是将一类对象共同的特征抽取出来的结果,是对象的蓝图和模板。
四大支柱
- 抽象(abstraction):寻找共性。定义类的过程就是一个抽象的过程,需要做数据抽象和行为抽象。
- 封装(encapsulation):隐藏一切可以隐藏的复杂繁琐的实现细节,只提供清晰简单的接口(界面)。
- 继承(inheritance):从已有的类创建新类的过程。提供继承信息的类叫父类(超类、基类),得到继承信息的类叫子类(派生类、衍生类)。
- 多态(polymorphism):执行相同的行为却做了不同的事情(产生了不同的结果)。
定义类
创建和使用对象
发现问题域中的类
从问题描述中找名词和动词,名词会成为类或者对象的属性,动词会成为对象的方法。
类的结构
public class 类名 {
// 属性(数据抽象)
// 构造器
// 方法(行为抽象)
}
创建和使用对象的语法
类型 变量名 = new 构造器([参数列表]);
变量名.方法([参数列表]);
练习1:写一个类,模拟数字时钟。
import java.util.Calendar;
/**
* 时钟
* @author jackfrued
*
*/
public class Clock {
private int hour; // 时
private int minute; // 分
private int second; // 秒
/**
* 构造器
*/
public Clock() {
Calendar cal = Calendar.getInstance();
hour = cal.get(Calendar.HOUR_OF_DAY);
minute = cal.get(Calendar.MINUTE);
second = cal.get(Calendar.SECOND);
}
/**
* 构造器
* @param hour 时
* @param minute 分
* @param second 秒
*/
public Clock(int hour, int minute, int second) {
this.hour = hour;
this.minute = minute;
this.second = second;
}
/**
* 走字
*/
public void go() {
second += 1;
if(second == 60) {
second = 0;
minute += 1;
if(minute == 60) {
minute = 0;
hour += 1;
if(hour == 24) {
hour = 0;
}
}
}
}
/**
* 显示时间
* @return 返回当前时间
*/
public String display() {
String str = "";
if(hour < 10) {
str += "0";
}
str += hour + ":";
if(minute < 10) {
str += "0";
}
str += minute + ":";
if(second < 10) {
str += "0";
}
str += second;
return str;
}
/**
* 调整小时
* @param up true表示上调, false表示下调
*/
public void setHour(boolean up) {
if(up) {
hour = (hour + 1) % 24;
}
else {
hour -= 1;
if(hour == -1) {
hour = 23;
}
}
}
/**
* 调整分钟
* @param up true表示上调, false表示下调
*/
public void setMinute(boolean up) {
if(up) {
minute = (minute + 1) % 60;
}
else {
minute -= 1;
if(minute == -1) {
minute = 59;
}
}
}
/**
* 调整秒
* @param up true表示上调, false表示下调
*/
public void setSecond(boolean up) {
if(up) {
second = (second + 1) % 60;
}
else {
second -= 1;
if(second == -1) {
second = 59;
}
}
}
}
package com.lovoinfo;
public class Test03 {
public static void main(String[] args) throws Exception {
Clock c = new Clock();
while(true) {
System.out.println(c.display());
Thread.sleep(1000);
c.go();
}
}
}
练习2:计划修一个圆形的游泳池,半径尚未确定,游泳池的外围修建宽度为3m的环形过道,过道的外围修建一圈围墙,已知围墙的造价为5元/m,过道的造价为18元/m^2^,写一个程序,输入游泳池的半径,计算出过道和围墙的造价。
package com.lovoinfo;
// 1. 定义类(数据抽象[属性]、行为抽象[方法]、构造器)
/**
* 圆
* @author jackfrued
*
*/
public class Circle {
private double radius; // 半径
/**
* 构造器
* @param radius 半径
*/
public Circle(double radius) {
this.radius = radius;
}
/**
* 获得周长
* @return 圆的周长
*/
public double circumference() {
return 2 * Math.PI * radius;
}
/**
* 获得面积
* @return 圆的面积
*/
public double area() {
return Math.PI * radius * radius;
}
}
package com.lovoinfo;
import java.util.Scanner;
public class Test01 {
private static final double FUNIT = 5.5; // 围墙的单位造价
private static final double CUNIT = 18; // 过道的单位造价
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入游泳池的半径: ");
double r = sc.nextDouble();
// 2. 创建对象
Circle c1 = new Circle(r);
Circle c2 = new Circle(r + 3);
// 3. 让对象发生行为(对象调用方法)求解问题
System.out.printf("围墙的造价为: ¥%.2f元\n",
c2.circumference() * FUNIT);
System.out.printf("过道的造价为: ¥%.2f元\n",
(c2.area() - c1.area()) * CUNIT);
sc.close();
}
}
练习3:学生类和老师类。
package com.lovoinfo;
/**
* 人(父类)
* @author jackfrued
*
*/
public class Person {
protected String name; // 姓名
protected int age; // 年龄
/**
* 构造器
* @param name 姓名
* @param age 年龄
*/
public Person(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 吃饭
*/
public void eat() {
System.out.println(name + "在吃饭");
}
/**
* 睡觉
*/
public void sleep() {
System.out.println(name + "在睡觉");
}
/**
* 玩耍
*/
public void play() {
}
}
package com.lovoinfo;
/**
* 学生(人的子类)
* @author jackfrued
*
*/
public class Student extends Person {
private String grade; // 年级
/**
* 构造器
* @param name 姓名
* @param age 年龄
* @param grade 年级
*/
public Student(String name, int age, String grade) {
super(name, age); // 调用父类构造器
this.grade = grade;
}
/**
* 学习
* @param courseName 课程名称
*/
public void study(String courseName) {
System.out.println(name + "在学习" + courseName);
}
/**
* 玩耍(对父类中的play方法进行重新实现[重写])
*/
public void play() {
System.out.println(name + "在玩LOL");
}
@Override
public String toString() {
return name + " - " + age + " - " + grade;
}
}
package com.lovoinfo;
/**
* 老师(人的子类)
* @author jackfrued
*
*/
public class Teacher extends Person {
private String title; // 职称
/**
* 构造器
* @param name 姓名
* @param age 年龄
* @param title 职称
*/
public Teacher(String name, int age, String title) {
super(name, age);
this.title = title;
}
/**
* 授课
* @param courseName 课程名称
*/
public void teach(String courseName) {
System.out.println(name + "正在教" + courseName);
}
/**
* 玩耍(对父类中的play进行重新实现[重写])
*/
public void play() {
System.out.println(name + "在打麻将");
}
@Override
public String toString() {
return name + " - " + age + " - " + title;
}
}
练习4:编程模拟银行账户及其操作。
package com.lovoinfo;
/**
* 银行账户
* @author jackfrued
*
*/
public class Account {
private String cardNumber; // 卡号
private String password; // 密码
private double balance; // 余额
/**
* 构造器
* @param cardNumber 卡号
* @param password 初始密码
*/
public Account(String cardNumber, String password) {
this.cardNumber = cardNumber;
this.password = password;
this.balance = 0.0;
}
/**
* 验证密码
* @param thyPassword 输入的密码
* @return 验证通过返回true否则返回false
*/
public boolean verify(String thyPassword) {
return password.equals(thyPassword);
}
/**
* 取款
* @param money 取款金额
* @return 取款成功返回true否则返回false
*/
public boolean withdraw(double money) {
if(money > 0 && money <= balance) {
balance -= money;
return true;
}
return false;
}
/**
* 存款
* @param money 存款金额
* @return 存款成功返回true否则返回false
*/
public boolean deposit(double money) {
if(money > 0) {
balance += money;
return true;
}
return false;
}
/**
* 转账
* @param other 转入账户
* @param money 转出金额
* @return 转账成功返回true否则返回false
*/
public boolean transfer(Account other, double money) {
if(this.withdraw(money)) { // 如果当前账户扣款成功才能向转入账户存钱
boolean flag = other.deposit(money);
if(!flag) { // 如果向转入账户存钱不成功则应返还转出金额
this.deposit(money);
}
return flag;
}
return false;
}
/**
* 查询余额
* @return 账户余额
*/
public double getBalance() {
return balance;
}
/**
* 获得卡号
* @return 卡号
*/
public String getCardNumber() {
return cardNumber;
}
/**
* 修改密码
* @param newPassword 新密码
*/
public void changePassword(String newPassword) {
this.password = newPassword;
}
}
练习5:双色球随机选号程序。
package com.lovoinfo;
/**
* 球
* @author jackfrued
*
*/
public class Ball {
private int number; // 数字
private boolean used; // 是否被使用过
/**
* 构造器
* @param number 球上面的数字
*/
public Ball(int number) {
this.number = number;
// this.used = false;
}
/**
* 球是否被使用过
* @return 使用过返回true否则返回false
*/
public boolean isUsed() {
return used;
}
/**
* 设置球有没有被使用过
* @param used true表示使用过false表示没有使用过
*/
public void setUsed(boolean used) {
this.used = used;
}
/**
* 获得球上的号码(如果号码小于10前面要补0)
* @return 号码补0后的字符串
*/
public String getNumber() {
return number < 10? "0" + number : "" + number;
}
/**
* 获得球上的号码
* @return 号码的数字
*/
public int getNum() {
return number;
}
}
package com.lovoinfo;
/**
* 双色球选号机
* @author jackfrued
*
*/
public class LotteryMachine {
private Ball[] redBalls = new Ball[33]; // 33个红球
private Ball[] blueBalls = new Ball[16]; // 16个蓝球
// 装入红色球和蓝色球
public void load() {
for(int i = 0; i < redBalls.length; i++) {
redBalls[i] = new Ball(i + 1); // 创建一颗球
}
for(int i = 0; i < blueBalls.length; i++) {
blueBalls[i] = new Ball(i + 1);
}
}
// 摇出6个红色球
public Ball[] getRedBalls() {
Ball[] rBalls = new Ball[6];
for(int i = 0; i < rBalls.length; i++) {
Ball currentBall = null;
do {
int index = (int) (Math.random() * redBalls.length);
currentBall = redBalls[index];
} while(currentBall.isUsed());
rBalls[i] = currentBall;
currentBall.setUsed(true);
}
for(int i = 1; i < rBalls.length; i++) {
for(int j = 0; j < rBalls.length - i; j++) {
if(rBalls[j].getNum() > rBalls[j + 1].getNum()) {
Ball temp = rBalls[j];
rBalls[j] = rBalls[j + 1];
rBalls[j + 1] = temp;
}
}
}
return rBalls;
}
// 摇出1个蓝色球
public Ball getBlueBall() {
return blueBalls[(int) (Math.random() * blueBalls.length)];
}
// 产生一个随机号码
public String generateRandomNumber() {
load(); // 装入红色球和蓝色球
Ball[] myRedBalls = getRedBalls(); // 摇出6个红色球
Ball myBlueBall = getBlueBall(); // 摇出1个蓝色球
String myNumber = "";
for(int i = 0; i < myRedBalls.length; i++) {
myNumber += myRedBalls[i].getNumber() + " ";
}
myNumber += "|";
myNumber += " " + myBlueBall.getNumber();
return myNumber;
}
}
import java.util.Scanner;
public class Test06 {
public static void main(String[] args) {
LotteryMachine lm = new LotteryMachine();
Scanner sc = new Scanner(System.in);
System.out.print("机选几注: ");
int n = sc.nextInt();
for(int i = 1; i <= n; i++) {
System.out.println(lm.generateRandomNumber());
}
sc.close();
}
}
作业:德玛打小龙
父类
public class DeMarcia {
protected int damage; //攻击力
protected int vitality; //生命
/**
* 构造器
* @param damage 构造攻击力
* @param vitality 构造血
*/
public DeMarcia(int damage, int vitality) {
this.damage = damage;
this.vitality = vitality;
}
子类
public class Dargon extends DeMarcia{
/**
* 继承
* @param damage 攻击力
* @param vitality 血
*/
public Dargon(int damage, int vitality) {
super(damage, vitality);
}
public class Test01 {
public static void main(String[] args) {
/**
* 提取数据
*/
DeMarcia deMarcia = new DeMarcia(1000, 1500);
Dargon dargon = new Dargon(1, 10000);
do {
System.out.println("小龙攻击德玛,德玛血下降"+ dargon.damage);
deMarcia.vitality = deMarcia.vitality-dargon.damage;
System.out.println("德玛的血还剩"+ deMarcia.vitality);
System.out.println("德玛攻击小龙,小龙血下降"+deMarcia.damage );
dargon.vitality = dargon.vitality - deMarcia.damage;
System.out.println("小龙的血还剩"+dargon.vitality);
}while(dargon.vitality > 0);
System.out.println("德玛消灭小龙,全团移动属性增加\n");
System.out.println("\n");
}
}