访问控制与封装

访问控制与封装

1 package包

1.1 什么是package

Java中利用package对类进行分类,方便管理代码,package还定义了命名空间,减少了命名冲突,不同的包中可以定义同名类。

使用包:

  • 必须在Java源文件的第一行使用package声明包,package语句只能有一行
  • package可以不写,不写表示使用默认包
  • package相同的类放置在同一个包中
  • 包名要符合java命名规范(包名采用小写字母)
  • 一个包中可以定义多个类,但是类名不能同名
  • 包编译以后变成多对应的文件夹
1.2 全限定名和import

全限定名:也称为全名,是指由包名和类名组成的完整名称。遇到相同类名时候不能省略包名。

案例:

package demo02;
public class Foo{
}
package demo03;
public class Foo{
}
package demo01;
public class Demo01{
    public static void main(String[] args){
        //使用全限定名访问其他包中的类
        demo02.Foo foo=new demo02.Foo();
        demo03.Foo foo2=new demo03.Foo();
    }
}
package demo01;
import demo02.Foo;
//import Demo02.Foo;//在Java源文件中不能同时导入同名类
public class Demo01{
    public static void main(String[] args){
        /*
         *使用import导入其他包中的类,可以直接使用,不需要全限定名
         */
        Foo foo=new Foo();
        //如果需要在一个源文件中使用两个同名类,就必须使用全限定名访问
        demo03.Foo foo2=new demo03.Foo();
    }
}

2 访问控制与封装

2.1 什么是访问控制

访问控制:用于设定类,属性,方法等资源的可见范围。利用访问控制可以控制数据及方法的可见范围,避免意外篡改,保护软件组件(对象)的安全可靠。

2.2 访问控制修饰词属性

4个访问修饰词:

  • public 公有的,修饰类,修饰属性,修饰方法,修饰构造器
  • protected 保护的,修饰类中的成员:属性,方法,构造器等
  • 默认的,不写任何修饰词,修饰类,修饰属性,修饰方法,修饰构造器
  • private 私有的,修饰类中的成员:属性、方法、构造器等
2.3 public和private

public 是公有的,其可见范围最大,被修饰资源可以在任何位置使用

private是私有的,其可见范围最小,被修饰的资源仅仅在当前类体内部可见。

案例:+

package demo04;
public class Goo{
    private int a=6;
    public int b=5;
    public int add(){
        //私有属性a可以在类内部访问,属性a属于当前类私有
        return a+b;
    }
}
package demo05;
import demo04.Goo;
public calss Demo04{
    public static void main(String[] args){
        /*
         *测试public和private的区别
         */
        Goo goo=new Goo();
        //System.out.println("goo.a");//编译错误,不可见
        System.out.println("goo.b");//公有属性可以访问
        System.out.println("goo.add");//公有方法可以访问
    }
}
2.4 public 与默认

案例:

package demo06;
public calss Koo{
    int a=6;//默认修饰
    public int b=5;//公有修饰
}
package demo06;
public class Demo05{
    public static void main(String[] args){
         /*
         *访问公有和默认的属性
         */
        Koo koo=new Koo();
        //同一个包demo06中可以访问默认属性
        System.out.println("koo.a");
        //同一个包中也可以访问公有属性
        System.out.println("koo.b");
    }
}
package demo07;
import demo06.Koo;
public class Demo06{
    public static void main(String[] args){
         /*
         *访问公有和默认的属性
         */
        Koo koo=new Koo();
        //不在同一个包demo06中不能访问默认属性
        System.out.println("koo.a");
        //同一个包中也可以访问公有属性
        System.out.println("koo.b");
    }
}
2.5 protected与默认

protected修饰的资源其可见范围是子类和当前包内部可见,子类“泛化”到父类中的属性和方法经常定义为保护的。

package demo08;
public class Xoo{
    protected int a=6;//保护属性
    int b=8;//默认属性
}
package demo08;
public class Demo07{
    public static void main(String[] args){
        /*
         *在同一个包中访问默认和保护的属性
         */
        Xoo xoo=new Xoo();
        System.out.println("Xoo.a");
        System.out.println("Xoo.b");
    }
}
package demo09;
import demo08.Xoo;
public class Demo08{
    public static void main(String[] args){
        /*
         *不在同一个包的时候,访问另一个包中的默认和保护属性
         */
        Xoo xoo=new Xoo();
        //默认和保护的属性都是包内可见
        //System.out.println("Xoo.a");//不可见
        //System.out.println("Xoo.b");//不可见
    }
}
package demo09;
import demo08.Xoo;
public class Yoo extends Xoo{
    public void test(){
        //在子类中可以访问继承到的保护属性
        System.out.println(a);
        //默认属性,不支持跨包访问
        System.out.println(b);
    }
    public static void main(String[] args){
        Yoo yoo=new Yoo();
        yoo.test();
    }
}
2.6 封装

面向对象三大基本特征:封装,继续,多态。

封装是指:一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。也是一种防止外界调用端,去访问对象内部实现细节的手段。

简单理解:封装数据和算法细节,暴露可以安全访问的方法和数据。

Java中的封装就是采用访问修饰词实现的:

  • 需要隐藏的属性和方法定义为私有的private
  • 需要留给子类使用的属性和方法定义为保护的protected
  • 确实需要公开访问的属性和方法定义公有的public
  • 默认的访问控制不使用
2.7 飞机大战中的封装

案例:

package demo10;
import java,awt.Graphics;
import javax.swing.ImageIcon;
/*
 * 父类中定义从子类抽取的属性和方法
 * 这种抽取方式称为“泛化”
 */
public class FlyingObject {
	 protected double x;
	 protected double y;
	 protected double width;
	 protected double height;
     protected double step;
     protected ImageIcon image;
    
    public FlyingObject(double x, double y, double width, double height) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
    }
    public void move(){
        y+=step;
    }
    public void paint(Graphics g){
        image.paintIcon(null,g,(int)x, (int)y);
    }
	@Override
	public String toString() {
        String className=getClass().getName();
		return className+" [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]";
	}
}
package demo10;
import java.awt.Graphics;
import javax.swing.ImageIcon;
public class Sky extends FlyingObject{

 	protected double yo;
	public Sky(double x, double y, double width, double height, double step) {
		super(x,y,width,height);
		this.step =step;
		this.image=new ImageIcon("images/background.png");
		x=0;
		y=0;
		yo=-image.getIconHeight();//照片的高度
		height=image.getIconHeight(); //天空的高度(照片)
		width=image.getIconWidth();//天空的宽度(照片)
		System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
	}
	public void move() {
		y+=step;
		yo+=step;//(两个坐标都在移动)

		if(y>=height) {
			//System.out.println("第一个照片返回:y="+y);
			y=-height;
            //System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
		}
		if(yo>=height) {
			//System.out.println("第二个照片返回:y0="+yo);
			yo=-height;
			//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
		}
	}
	public void paint(Graphics g) {//改写父类中的方法
		image.paintIcon(null, g, (int)x, (int)y);
		image.paintIcon(null, g, (int)x, (int)yo);//对天空做修改,对两张照片进行处理
	}
}
package demo10;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class World extends JPanel{
	/*
	 * 添加飞机大战世界中的物体
	 */
	private Airplane[] airplanes;
    private Bigplane[] bigplanes;
    private Bullet[]bullets;
    private Sky sky;
    private Hero hero;
    
	/*
	 * 利用构造器初始化世界中每个物体
	 */
	public World(){
		airplanes=new Airplane[2];//创建两个元素的数组
		airplanes[0]=new Airplane(10,10,1.5);//宽高去掉了50,40
		airplanes[1]=new Airplane(10,100,1.5);
		//x,y   宽      高        速度
		bigplanes=new Bigplane[2];
		bigplanes[0]=new Bigplane(100,20,2);//宽高去掉了100,200
		bigplanes[1]=new Bigplane(100,220,2);
	
		bullets =new Bullet[6];
		bullets[0]=new Bullet(200,400,4);//宽高去掉了10,10
		bullets[1]=new Bullet(200,350,4);
        bullets[2]=new Bullet(200,300,4);
        bullets[3]=new Bullet(200,250,4);
        bullets[4]=new Bullet(200,200,4);
        bullets[5]=new Bullet(200,150,4);

		sky=new Sky(0,0,400,700,0.8);
		hero=new Hero(200,500,200,200);
	}

	public void paint(Graphics g) {
        sky.paint(g);
		hero.paint(g);

		for(int i=0; i<bullets.length; i++) {
			//i=0  1  2  3  4  5
			bullets[i].paint(g);
		}
		//调用每个飞机的多态方法,实现多态的绘制
		for(int i=0; i<planes.length; i++) {
			airplanes[i].paint(g);
		}
        for(int i=0; i<planes.length; i++) {
			bigplanes[i].paint(g);
		}
	}

	public static void main(String[] args) {
		JFrame frame=new JFrame();
		World world=new World();
		frame.add(world);
		frame.setSize(400,700);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
        //调用action方法启动定时器
        world.action();
	}
    /*
	 * 添加内部类,实现定时计划任务
	 * 为何使用内部类实现定时任务
	 * 1.隐藏定时任务到world类中
	 * 2.可以访问外部类中的数据,飞机,子弹等
	 */
   private class PaintTask extends TimerTask{
        public void run(){//执行飞机移动方法;是多态的移动方法,每个飞机都不同
            for(int i=0; i<airplanes.length; i++){
                airplanes[i].move();
            }
            for(int i=0; i<bigplanes.length; i++){
                bigplanes[i].move();
            }
            for(int i=0; i<bullets.length; i++){
                bullets[i].move();
            }
            sky.move();
            repaint();	//调用重写绘制方法,这个方法会自动执行paint
        }
    }
    public void action(){//启动方法
        Timer timer=new Timer();
        PaintTask task=new PaintTask();//定时器任务
        timer.schedule(task,1000,1000/100);//规定计划每间隔多少时间执行
    }
}

访问控制与封装

3 final最终

Java中final可以修饰变量,修饰方法,修饰类

  • 变量:可以初始化,不能再更改‘
  • 方法:不能在子类中重写
  • 类:不能再被继承派生出子类了
3.1 final局部变量

在方法中声明的变量称为局部变量。只能初始化一次,不能再更改,目的是保护局部变量的值不变,避免篡改。

package demo11;
import java.util,Arrays;
public class Demo01 {
	public static void main(String[] args) {
		/*
		 * final局部变量现象
		 */
		final int a;
		a=8;//第一次为变量赋值,称为初始化
		System.out.println(a);
		//a=9;//编译错误,a不能再次被修改
		final int b=9;//声明变量直接初始化
		System.out.println(b);
		//b=10;//不能再次修改final变量
		int c=8;
		c=6;
		System.out.println(c);//6

		final int C=300000;
		//C++;不能再修改变量C
		System.out.println(C);

		//final修饰的引用类型变量
		//引用类型变量初始为一个地址值后不能再次修改
		final int[] arr= {5,6};//arr中储存的数组地址不能再次修改类
		//arr引用不能修改,但是被引用对象内容可以修改
		arr[0]=9;
		System.out.println(Arrays.toString(arr));//[9,6]
		//不可以更改arr变量的值,因为arr是final类型的
		//arr=new int [8];

		final Ball ball=new Ball();
		ball.d=10;
		System.out.println(ball.d);
        
		//不能更换ball的值,也就是地址值
		//ball=null;

		final Girl gf=new Girl();
		gf.age++;//年龄可增长
		System.out.println(gf.age);
		//gf=new Girl();对象不能变
	}
}
class Girl{
	int age=18;
}

class Ball{
	int d=5;
}
3.2 final修饰方法参数
public class Demo2 {
	public static void main(String[] args) {
		/*
		 * final修饰的方法参数
		 * 1,方法参数是局部变量,在传递参数时初始化
		 * 2,final 的方法参数,在接受参数初始化以后不能再次修改
		 */
		test(5,6);
		test(7,8);
	}
	public static void test(int a, final int b) {
		a=9;
		//b=8;//编译错误,不能再次更改变量b
		System.out.println("a:"+a+",b:"+b);//a=9,b=6//a=9,b=8
	}
}
3.3 final修饰实例变量

在类中声明的对象属性称为“实例变量”。实例变量在初始化后不能再次改变。目的也是保护实例变量。

案例:

package demo11;
public class Demo3 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 演示final的实例变量(对象属性)
		 */
		Eoo eoo=new Eoo(8);
		System.out.println(eoo.a);//5
		System.out.println(eoo.b);//8
		//不能再次更改final的实例变量
		//eoo.a=9;
		//eoo.b=9;

		Eoo e2=new Eoo(10);
		System.out.println(e2.a);//5
		System.out.println(e2.b);//10
	}
}
class Eoo{
	//final的属性必须初始化
	final int a=5;
	final int b;
	public Eoo(int b) {
		this.b=b;
	}
}
3.4 final方法

final的方法在子类中不能被重写修改。

简单理解:final方法不能被重写,final修饰的方法不会影响方法在当前类中的使用,但是如果派生了子类,则在子类中不能重写修改父类中定义的final方法。

案例:

package demo11;
public class Demo4 {
	public static void main(String[] args) {
		/*
		 * final方法可以被子类继承,但是不能被子类重写
		 */
		Foo foo=new Foo();
		foo.test();

		SubFoo sf=new SubFoo();
		sf.test();
	}
}
class Foo{
	public final void test() {
		System.out.println("Foo.test()");
	} 
}
class SubFoo extends Foo{
	//public void test();编辑错误,不能重写FOO中的final方法
	// System.out.println("SubFoo.test()");  
}
3.5 final类

final类不能被继承。

package demo11;
public class Demo5 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 测试final类
		 */
		Goo goo=new Goo();
		goo.test();
	}
}
final class Goo{
	public void test() {
		System.out.println("test()");
	}
}
//class SubGoo extends Goo{//编译错误,不能继承final类
}
3.6 final总结
  • 变量:可以初始化,不能再更改,很常用
  • 方法:不能在子类中重写,不常用
  • 类:不能再被继承派生出子类了,不常用

4 静态

static翻译为静态,可以修饰成员变量、方法,可以与final联合使用修饰常量。

4.1 成员变量

三种:

  • 实例变量:属于每个对象属性,每个对象中都有一份
  • 静态变量:属于类的变量,只有一份,全体对象共享的同一份变量
  • 常量:不变的常数

成员变量:

class Foo{
    int a=5;//实例变量
    static int b=6;//静态变量
    static final int c=30;//常量
}
4.2 静态变量

软件中只有一份的数据应该使用ststic修饰。

package demo12;
public class Demo01 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 演示静态变量功能
		 * 实例变量a;每个对象都有一个实例变量
		 * 静态变量b;属于类的一份变量,全体对象共享同一个b
		 */
		Foo h1=new Foo();
		Foo h2=new Foo();
		h1.a=8;
		h2.a=10;
		Foo.b =11;//使用类名访问静态变量
		System.out.println(h1.a+","+h1.b);//8,11
		System.out.println(h2.a+","+h2.b);//10,11
		System.out.println(Foo.b);//11,读取静态变量
	}
}
class Foo{
	int a;//实例变量
	static int b;//静态变量
}
4.3静态变量工作原理
  1. Java源文件经过编译得到字节码文件,每个类编译为一个class文件

  2. 当执行Java程序时候,每用到一个类Java就会自动将对应的字节码加载到方法区

    • 创建对象时会自动加载类
    • 访问类的静态属性时候会自动加载类
    • 执行类中的静态方法时候会自动加载类
    • 字节码文件只加载一次
  3. 如果类中有静态变量,Java就会在加载类期间将其在方法区中分配出来,静态变量也初始化一次,只有一份

  4. 创建对象时候按照类中声明的实例变量分配对象的属性,每创建一个对象,就会分配一组对象属性。

4.4 静态方法

静态方法就是在声明方法时候添加static关键字。可以直接使用类名直接引用方法。

静态方法没有隐含的局部变量this,对象方法中保护隐含局部变量this。

静态方法不能访问实例变量和对象方法,因为main方法也是静态方法,所有main方法也不能访问当前类型的实例变量和对象方法。

案例:

package demo12;
public class Demo02 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*
		 * 静态方法演示
		 */
		Person.add(7,8);//用类名调用静态方法
		Person tom=new Person("Tom");
		tom.whoru();//用对象引用调用对象的方法
	}
}
class Person{
	String name;
	public Person(String name) {
		this.name=name;
	}
	public void whoru() {
		//对象方法中包含隐含局部变量this
		System.out.println("我是"+this.name);//Tom
	}
	//如果方法中没有用到当前对象的属性/方法就声明为static
	public static void add(int a, int b) {
		//静态方法中没有隐含局部变量this
		System.out.println(a+b);//15
	}
}
4.5 静态代码块

用于初始对象属性(很少使用)

class Cell{
    int a;
    {
        //代码块,在创建对象时执行
        a=(int)(Math.random()*8);
	}
}
package demo12;
public class Demo03 {
	public static void main(String[] args) {
		/*
		 * 测试静态代码块
		 * java会在创建对象之前自动加载类Circle
		 */
		Circle c1=new Circle();
		Circle c2=new Circle();
		System.out.println(Circle.angle);		
	}
}
class Circle{
	static double angle;//角
	static {//在类加载期间执行,只执行一次
		System.out.println("初始化angle");
		angle=Math.PI*2;
	}
}
4.6 static final

常量用于声明不会变化的量。

软件中的常量:

  • 软件中不能改变的数据都应定义为常量
  • 同时使用static final修饰,顺序可以调换
  • 常量必须初始化
  • 一般变量名都是大写字母,多个单词使用下划线隔开:Max_VALUE

Java APL提供很多常量:

  • Math.PI、Math.E
  • integer.MAX_VALUE、integer.MIN_VALUE
  • Long.MAX_VALUE、Long.MIN_VALUE
4.7静态导入

import static称为静态导入:

import static java.lang.Math.PI;
import static java.lang.Math.sin;
import static java.lang.Math.*;

Java 8 提供了静态导入语法,用于简化静态资源的编码。

package demo11;
public class Demo04 {
	public static void main(String[] args) {
        /*
         *输出30,60,75,90的正弦值
         *Math.sin()正弦函数,参数必须是弧度
         *Math.toRadians()角度转换函数,将角度转换为弧度
         *PI/2是90度角
         */
		System.out.println(Math.sin(Math.toRadians(30)));
		System.out.println(Math.sin(Math.toRadians(60)));
		System.out.println(Math.sin(Math.toRadians(75)));
		System.out.println(Math.sin(Math.toRadians(90)));
		System.out.println(Math.sin(Math.PI/2));
	}
}

采用静态导入解决冗余繁琐:

package demo11;
import static java.lang.Math.*;
public class Demo05 {
	public static void main(String[] args) {
		System.out.println(sin(toRadians(30)));
		System.out.println(sin(toRadians(60)));
		System.out.println(sin(toRadians(75)));
		System.out.println(sin(toRadians(90)));
		System.out.println(sin(PI/2));
	}
}

5 重构飞机大战

5.1 声明images类

实现思路:由于图片属于静态资源,加载一份以后为与各种飞行物进行共享即可,再基于功能分治的原则进行设计

  1. 设计一个图片资源管理类images,在images中定义静态变量管理图片

  2. 在images中添加静态代码块,用于初始化静态图片资源

    a.单张图片利用静态图片变量储存

    b.多张图片利用静态图片数组储存

  3. 对图片资源加载结果进行单元测试

package demo13;
import javax.swing.ImageIcon;
public class Images {//管理图片
	public static ImageIcon[] airplane;
	public static ImageIcon[] bigplane;
	public static ImageIcon[] bee;
	public static ImageIcon bullet;
	public static ImageIcon[] hero;
	public static ImageIcon[] bom;
	public static ImageIcon sky;
	public static ImageIcon start;
	public static ImageIcon pause;
	public static ImageIcon gameover;
	static {//先创建数组,然后对数组初始化
		airplane=new ImageIcon[2];
		airplane[0]=new ImageIcon("images/airplane0.png");
		airplane[1]=new ImageIcon("images/airplane1.png");

		bigplane=new ImageIcon[2];
		bigplane[0]=new ImageIcon("images/bigairplane0.png");
		bigplane[1]=new ImageIcon("images/bigairplane1.png");

		bee=new ImageIcon[2];
		bee[0]=new ImageIcon("images/bee0.png");
		bee[1]=new ImageIcon("images/bee1.png");

		bullet=new ImageIcon("images/bullet.png");

		hero=new ImageIcon[2];
		hero[0]=new ImageIcon("images/hero0.png");
		hero[1]=new ImageIcon("images/hero1.png");

		bom=new ImageIcon[4];
		bom[0]=new ImageIcon("images/bom1.png");
		bom[1]=new ImageIcon("images/bom2.png");
		bom[2]=new ImageIcon("images/bom3.png");
		bom[3]=new ImageIcon("images/bom4.png");

		sky=new ImageIcon("images/background.png");

		start=new ImageIcon("images/start.png");

		pause=new ImageIcon("images/pause.png");

		gameover=new ImageIcon("images/gameover.png");
	}
	public static void main(String[] args) {
        //单元测试方法
		System.out.println(airplane[0].getImageLoadStatus());//8
		System.out.println(airplane[1].getImageLoadStatus());//8
		System.out.println(bigplane[0].getImageLoadStatus());//8
		System.out.println(bigplane[1].getImageLoadStatus());//8
		System.out.println(bee[0].getImageLoadStatus());//8
		System.out.println(bee[1].getImageLoadStatus());//8
		System.out.println(bullet.getImageLoadStatus());//8
		System.out.println(hero[0].getImageLoadStatus());//8
		System.out.println(hero[1].getImageLoadStatus());//8
		System.out.println(bom[0].getImageLoadStatus());//8
		System.out.println(bom[1].getImageLoadStatus());//8
		System.out.println(bom[2].getImageLoadStatus());//8
		System.out.println(bom[3].getImageLoadStatus());//8
		System.out.println(sky.getImageLoadStatus());//8
		System.out.println(start.getImageLoadStatus());//8
		System.out.println(pause.getImageLoadStatus());//8
		System.out.println(gameover.getImageLoadStatus());//8
	}
}
5.2 重构飞机大构造器

将加载图片更换成从images获得图片。

子弹:

package demo13;
public class Bullet extends FlyingObject{
    
	public Bullet(double x, double y, double width, double height, double step) {
		//利用super()调用父类有参数构造器,复用了父类中构造器算法
		super(x,y,width,height);
		this.step = step;
        image=Images.bullet;
        width=image.getIconWidth();
        height=image.getIconHeight();
	}
    /**
     *重写继承与超类的move方法,作用就是修改了超类move行为
     *超类是向下移动,修改为向上移动
     */
    public void move(){
        y-=step;
    }
}

小飞机:

package demo13;
public class Airplane extends FlyingObject{
    
	public Airplane(double x, double y, double width, double height, double step) {
		//利用super()调用父类有参数构造器,复用了父类中构造器算法
		super(x,y,width,height);
		this.step = step;
        image=Images.airplane[0];
        width=image.getIconWidth();
        height=image.getIconHeight();
	}
}

大飞机:

package demo13;
public class Bigplane extends FlyingObject{
    
	public Bigplane(double x, double y, double width, double height, double step) {
		//利用super()调用父类有参数构造器,复用了父类中构造器算法
		super(x,y,width,height);
		this.step = step;
        this.image=Images.bigplane[0];
        width=image.getIconWidth();
        height=image.getIconHeight();
	}
}

蜜蜂:

package demo13;
public class Bee extends FlyingObject{
    public Bee(double x, double y, double width, double height, double step){
        super(x,y,width,height);
        this.step=step;
        this.image=Images.bee[0];
        width=image.getIconWidth();
        height=image.getIconHeight();
    }
    /**
     *重写父类型move方法修改为斜向飞行
     */
    public void move(){
        //调用父类型方法,复用父类型定义的算法
        super.move();//向下飞行
        x++;
    }
}

英雄:

package demo13;
public class Hero extends FlyingObject{
    
	public Hero(double x, double y, double height, double width) {
		super(x,y,width,height);
        this.image=Images.hero[0];
        width=image.getIconWidth();
        height=image.getIconHeight();
	}
	/*
	 * 重写move方法,空方法,目的是不动
	 * 修改超类中规定的向下飞,改成不动
	 */
	public void move() {
	}
	/*
	 *将鼠标机移动到鼠标位置X,Y
	 *@param x鼠标位置x
	 *@param y鼠标位置y
	 */
	public void move(int x, int y) {
		this.x=x;
		this.y=y;
	}
}

天空:

package demo13;
import java.awt.Graphics;
import javax.swing.ImageIcon;
public class Sky extends FlyingObject{

 	protected double yo;
	public Sky(double x, double y, double width, double height, double step) {
		super(x,y,width,height);
		this.step =step;
		this.image=Images.sky;
		x=0;
		y=0;
		yo=-image.getIconHeight();//照片的高度
		height=image.getIconHeight(); //天空的高度(照片)
		width=image.getIconWidth();//天空的宽度(照片)
		System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
	}
	public void move() {
		y+=step;
		yo+=step;//(两个坐标都在移动)

		if(y>=height) {
			//System.out.println("第一个照片返回:y="+y);
			y=-height;
            //System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
		}
		if(yo>=height) {
			//System.out.println("第二个照片返回:y0="+yo);
			yo=-height;
			//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
		}
	}
	public void paint(Graphics g) {//改写父类中的方法
		image.paintIcon(null, g, (int)x, (int)y);
		image.paintIcon(null, g, (int)x, (int)yo);//对天空做修改,对两张照片进行处理
	}
}
posted @ 2021-02-28 00:09  指尖上的未来  阅读(83)  评论(0)    收藏  举报