JSD-2204-面向对象-抽象-潜艇游戏--Day12

本文探讨了Java中static final常量的使用场景和特点,以及抽象方法和抽象类的概念和作用。在潜艇游戏的第六天,介绍了多个游戏类的设计,如Battleship、Bomb等,强调了代码复用和统一接口的重要性。最后补充了访问权限规则和设计原则,并对抽象方法的意义进行了讨论。
摘要由CSDN通过智能技术生成

1. static final常量:应用率高

  • 必须声明同时初始化
  • 由类名点来访问,不能被改变
  • 建议:常量名所有字母都大写,多个单词用_分隔
  • 编译器在编译时会将常量直接替换为具体的值,效率高
  • 何时用:数据永远不变,并且经常使用
     public class StaticFinalDemo {
         public static void main(String[] args) {
             System.out.println(Aoo.PI); //常常通过类名点来访问
             //Aoo.PI = 3.14159; //编译错误,常量不能被改变
             
             //1)加载Boo.class到方法区中
             //2)静态变量num一并存储到方法区中
             //3)到方法区中获取num的值并输出
             System.out.println(Boo.num);
     
             //编译器在编译时会将常量直接替换为具体的值,效率高
             //如下语句相当于:System.out.println(5);
             System.out.println(Boo.COUNT);
         }
     }
     
     //演示常量的特点
     class Boo{
         public static int num = 5; //静态变量
         public static final int COUNT = 5; //常量
     }
     
     //演示常量的语法
     class Aoo{
         public static final double PI = 3.14;
         //public static final int NUM; //编译错误,常量必须声明同时初始化
     }

2.抽象:abstract

2.1抽象方法

  • 由abstract修饰
  • 只有方法的定义,没有具体的实现(连{}都没有)

2.2抽象类

  • 由abstract修饰
  • 包含抽象方法的类必须是抽象类
  • 抽象类不能被实例化(new对象)
  • 抽象类是需要被继承的,派生类:
    • 重写所有抽象方法-----------------变不完整为完整
    • 也声明为抽象类--------------------一般不这么做
  • 抽象类的意义:
  • 封装共有的属性和行为---------------代码复用
  • 为所有派生类提供统一的类型------向上造型(代码复用)
  • 可以包含抽象方法,为所有派生类提供统一的入口(能点出来),同时达到强制必须重写的目的(相当于制定了一个标准)

3.潜艇游戏第六天:

  1. 设置窗口的宽和高为常量,适当地方做修改
  2. 画对象:(需求)
   1)想画对象需要获取对象的图片,每个对象都能获取图片,
     意味着获取图片行为为共有的行为,所以设计在SeaObject超类中,
     每个对象获取图片的行为都是不一样的,所以设计为抽象方法
     ---在SeaObject中设计抽象方法getImage()获取对象的图片
   2)重写getImage()获取对象的图片
     ---在6个类中重写getImage()返回对应的图片
   3)因为只有活着的对象才需要画到窗口中,所以需要设计对象的状态,
     每个对象都有状态,意味着状态为共有属性,所以设计在SeaObject超类中,
     状态一般都设计为常量,同时设计state变量表示当前状态
     ---在SeaObject中设计状态常量LIVE、DEAD,state变量表示当前状态
     在后期的业务中经常需要判断对象的状态,每个对象都能判断,
     意味着判断状态的行为为共有行为,所以设计在SeaObject中,
     每个对象判断状态的行为都是一样的,所以设计为普通方法
     ---在SeaObject中设计isLive()、isDead()判断对象状态
   4)数据(状态、图片、x坐标、y坐标)都有了就可以开画了,每个对象都能画,
     意味着画对象行为为共有行为,所以设计在SeaObject超类中,
     每个对象画的行为都是一样的,所以设计为普通方法
     ---在SeaObject中设计paintImage()画图片------具体怎么画,不要求掌握
   5)画图片的行为做好了,在窗口World类中调用即可    
     5.1)准备对象
     5.2)重写paint()方法------调用paintImage()完成画图片的功能

3.1.1Battleship类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 战舰
 */
public class Battleship extends SeaObject{
    /**
     * 命
     */
    private int life;


    public Battleship() {
        super(66,26,270,124,5);
        this.life = 5;
    }


    @Override
    public void move() {

    }

    @Override
    public ImageIcon getImage() {
        return Images.battleship;
    }


    /**
     * 发射炸弹的方法
     */
    public void shootBomb(){

    }


}


3.1.2Bomb类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 炸弹
 */
public class Bomb extends SeaObject{

    public Bomb(int x , int y) {
        super(9,12,x,y,3);
    }


    /**
     * 炸弹移动的方法
     */
    @Override
    public void move() {
        y += speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.bomb;
    }


}


3.1.3Images类

package cn.tedu.submarine;

import javax.swing.ImageIcon;


public class Images {
    /**
     * 背景图
     */
    public static ImageIcon sea;
    /**
     * 战舰图
     */
    public static ImageIcon battleship;
    /**
     * 炸弹图片
     */
    public static ImageIcon bomb;
    /**
     * 游戏结束
     */
    public static ImageIcon gameover;
    /**
     * 水雷图片
     */
    public static ImageIcon mine;
    /**
     * 水雷潜艇
     */
    public static ImageIcon minesubm;
    /**
     * 侦察潜艇
     */
    public static ImageIcon obsersubm;
    /**
     * 鱼类潜艇
     */
    public static ImageIcon torpesubm;

    /**
     * 初始化图片
     */
    static {
        battleship = new ImageIcon("img/battleship.png");
        sea = new ImageIcon("img/sea.png");
        bomb = new ImageIcon("img/bomb.png");
        gameover = new ImageIcon("img/gameover.png");
        mine = new ImageIcon("img/mine.png");
        minesubm = new ImageIcon("img/minesubm.png");
        obsersubm = new ImageIcon("img/obsersubm.png");
        torpesubm = new ImageIcon("img/torpesubm.png");
    }

//    /**
//     * 测试图片
//     * @param args
//     */
//    public static void main(String[] args) {
//        //返回8表示成功了
//        System.out.println(battleship.getImageLoadStatus());
//    }

}


3.1.4Mine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 水雷
 */
public class Mine extends SeaObject{

    public Mine(int x , int y) {
        super(11,11,x,y,1);
    }


    /**
     * 水雷移动的方法
     */
    @Override
    public void move() {
        y-=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.mine;
    }


}


3.1.5MineSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 水雷潜艇
 */
public class MineSubmarine extends SeaObject{


    public MineSubmarine() {
        super(63,19);
    }


    /**
     * 水雷潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.minesubm;
    }

}


3.1.6ObserverSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 侦察潜艇
 */
public class ObserverSubmarine extends SeaObject{


    public ObserverSubmarine() {
        super(63,19);
    }


    /**
     * 侦察潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.obsersubm;
    }
}


3.1.7SeaObject类

package cn.tedu.submarine;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

/**
 * 海洋对象
 */
public abstract class SeaObject {
    public static final int LIVE = 0;//或者的
    public static final int DEAL = 1;//死了的
    protected int state = LIVE;//当前状态(默认是活着的)
    /**
     * 成员变量一般都要private的
     * 此处设计为protected
     * 因为还没有讲到getter/setter
     */
    /**
     * 宽
     */
    protected int width;
    /**
     * 高
     */
    protected int height;
    /**
     * x轴
     */
    protected int x;
    /**
     * y轴
     */
    protected int y;
    /**
     * 速度
     */
    protected int speed;


    public SeaObject(int width,int height,int x , int y,int speed){
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.speed = speed;
    }

    public SeaObject(int width,int height){
        this.width = width;
        this.height = height;
        Random rand = new Random();
        x = width;
        y = rand.nextInt(World.HEIGHT-height-150+1 ) +150;
        this.speed = rand.nextInt(3)+1;
    }

    /**
     * 移动的方法
     */
    public abstract void move();

    /**
     * 获取对象的图片
     */
    public abstract ImageIcon getImage();

    /**
     * 判断是活着的
     * @return
     */
    public boolean isLive(){
        return state == LIVE;
    }

    /**
     * 判断是死的吗
     * @return
     */
    public boolean isDeal(){
        return  state == DEAL;
    }

    /**
     * 画图片
     * @param g
     */
    public void paintImage(Graphics g){
        if (isLive()){//若或者的
            //不要求掌握
            this.getImage().paintIcon(null,g,this.x,this.y);
        }
    }
}


3.1.8TorpedoSubmarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 鱼类潜艇
 */
public class TorpedoSubmarine extends SeaObject{


    public TorpedoSubmarine() {
        super(64,20);
    }


    /**
     * 鱼类潜艇移动的方法
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.torpesubm;
    }

}


3.1.9World(测试类)

package cn.tedu.submarine;

import javax.swing.*;
import java.awt.Graphics;

/**
 * 整个游戏世界
 */
public class World extends JPanel {
    public static final int WIDTH = 641;//窗口的宽
    public static final int HEIGHT = 479;//窗口的高

    private Battleship  ship = new Battleship();//战舰
    private SeaObject[] submarines = {
            new ObserverSubmarine(),
            new MineSubmarine(),
            new TorpedoSubmarine()
    };//潜艇数组(侦察潜艇,鱼雷潜艇,水雷潜艇)
    private Mine[] mines = {
            new Mine(200,300)
    };//水雷数组
    private Bomb[] bombs = {
            new Bomb(180,130)
    };//炸弹数组

    /**
     * 重写JPanel中的paint()画  g 画笔
     * @param g
     */
    @Override
    public void paint(Graphics g) {
        Images.sea.paintIcon(null,g,0,0);//海洋图片
        ship.paintImage(g);
        //画敌人
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].paintImage(g);
        }
        //画水雷
        for (int i = 0; i < mines.length; i++) {
            mines[i].paintImage(g);
        }
        //画炸弹
        for (int i = 0; i < bombs.length; i++) {
            bombs[i].paintImage(g);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize( WIDTH+16,HEIGHT+39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);


    }
}

4.补充

4.1访问权限由大到小依次为:

  • public > protected > 默认的 > private

4.2设计规则:

  • 将派生类所共有的属性和行为,抽到超类中------------------抽共性
  • 若对象的行为都一样,设计为普通方法
  • 若对象的行为都不一样,设计为抽象方法

4.3抽象方法/抽象类的疑问:

  • 抽象方法存在的意义是什么? 
    • 保证当发生向上造型时,通过超类的引用能点出来那个方法
  • 既然意义只在于能点出来,那为什么不设计成普通方法呢?
    • 若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,则可以强制派生类必须重写------做了个标准,强制必须重写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值