抽象与接口之狐狸和兔子(上)

@spiritree  August 29, 2016

狐狸和兔子都有年龄
当年龄到一定的上限就死亡
狐狸可以随机决定在周围的兔子中吃一个
狐狸和兔子都可以随机决定生一个小的在周围的格子中
如果不吃不生,狐狸和兔子可以随机决定向旁边空格子进一步

概念图:
foxandrabbit

  • Animal包

Animal类

import java.util.ArrayList;
import field.Location;

public abstract class Animal {
    private int ageLimit;
    private int breedableAge;
    private int age;
    private boolean isAlive = true;

    public Animal(int ageLimit, int breedableAge) {
        this.ageLimit = ageLimit;
        this.breedableAge = breedableAge;
    }

    protected int getAge() {
        return age;
    }

    protected double getAgePercent() {
        return (double)age/ageLimit;
    }

    public abstract Animal breed();

    public void grow() {
        age++;
        if ( age >= ageLimit ) {
            die();
        }
    }

    public void die() {
        isAlive = false;
    }

    public boolean isAlive() {
        return isAlive;
    }

    public boolean isBreedable() {
        return age >= breedableAge;
    }

    public Location move(Location[] freeAdj) {
        Location ret = null;
        if ( freeAdj.length>0 && Math.random() < 0.02 ) {
            ret = freeAdj[(int)(Math.random()*freeAdj.length)];
        }
        return ret;
    }

    @Override
    public String toString() {
        return ""+age+":"+(isAlive?"live":"dead");
    }

    public Animal feed(ArrayList<Animal> neighbour) {
        return null;
    }

    protected void longerLife(int inc) {
        ageLimit += inc;
    }
}

Fox类

import cell.Cell;

public class Fox extends Animal implements Cell {
    public Fox() {
        super(20,4);
    }

    @Override
    public void draw(Graphics g, int x, int y, int size) {
        int alpha = (int)((1-getAgePercent())*255);
        g.setColor(new Color(0, 0, 0, alpha));//(int)((20-getAge())/20.0*255)));
        g.fillRect(x, y, size, size);
    }

    @Override
    public Animal breed() {
        Animal ret = null;
        if ( isBreedable() && Math.random() < 0.05 ) {
            ret = new Fox();
        }
        return ret;
    }

    @Override
    public String toString() {
        return "Fox:"+super.toString();
    }

    @Override
    public Animal feed(ArrayList<Animal> neighbour) {
        Animal ret = null;
        if ( Math.random()< 0.2 ) {
            ret = neighbour.get((int)(Math.random()*neighbour.size()));
            longerLife(2);
        }
        return ret;
    }
}

Rabbit类

import cell.Cell;

public class Rabbit extends Animal implements Cell {
    public Rabbit() {
        super(10,2);
    }

    @Override
    public void draw(Graphics g, int x, int y, int size) {
        int alpha = (int)((1-getAgePercent())*255);
        g.setColor(new Color(255, 0, 0, alpha));
        g.fillRect(x, y, size, size);
    }

    @Override
    public Animal breed() {
        Animal ret = null;
        if ( isBreedable() && Math.random() < 0.12 ) {
            ret = new Rabbit();
        }
        return ret;
    }

    @Override
    public String toString() {
        return "Rabbit:"+super.toString();
    }
}
  • 这种只有子类才知道如何实现的方法,一般被定义为抽象方法。

  • 定义了抽象方法的类必须被声明为抽象类,不过,抽象类可以没有抽象方法。抽象类和具体类一样,可以定义具体方法、实例变量等,它和具体类的核心区别是,抽象类不能创建对象,而具体类可以。

  • 抽象类不能创建对象,要创建对象,必须使用它的具体子类。一个类在继承抽象类后,必须实现抽象类中定义的所有抽象方法,除非它自己也声明为抽象类。

  • 抽象类和接口是配合而非替代关系,它们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。


添加新评论

  1. 有趣~

    Reply