学习面向对象第三节

1.引用变量的强制类型转换

public class ConverSionTest {
	public static void main(String[] args){
		double d=13.4;
		long l=(long)d;
		System.out.println(l);
		int in=5;
		//试图把一个数值类型的变量转换为boolean类型,下面代码编译出错
		//编译时会提示不可转换的类型
		//Boolean b=(Boolean)in;
		Object obj="Hello";
		//obj变量编译时类型是Object,Object和String存在继承的关系,可以强制类型转换
		//而且obj变量的实际类型是String,所以运行时也可以通过
		String objstr=(String)obj;
		System.out.println(objstr);
		///定义一个objPri变量,编译时类型是Object,实际类型是Integer
		Object objPri=new Integer(5);
		//objPri变量编译时类型为Object,Object的运行时类型为Integer
		//Object与Integer存在继承关系
		//可以强制类型转换,而ObjPri变量的实际类型是Integer
		//所以下面的会引发ClassCastException异常
		//String str=(String)objPri;
		//考虑到强制类型转换时可能出现异常,因此进行类型转换之前应先通过instanceof运算符类判断是否可以成功转换。
		//为了让程序更加健壮,可以将代码修改为以下形式
		if(objPri instanceof String){
			String str=(String)objPri;
		}else{
			System.out.println("不可以进行强制类型转换");
		}
	}
}
为了使程序更加的健壮,在强制类型转换之前,应该做一步判断,使用instanceof来判断该变量是否可以强制类型转换为另一种类型。从而避免出现ClassCastException异常,这样可以保证程序更加健壮。

注意:把子类对象赋给父类引用变量时,被称为向上转型(upcasting),这种转型总是可以成功。也从另一侧面证实子类是一种特殊的父类。

2.继承与组合

继承带来的高度复用的同时也带来了一个严重的问题:继承严重破坏了父类的封装性。前面介绍封装时提到了:每个类都应该封装他的内部类信息和实现细节,而只暴露必要的方法给其他类使用,但在继承关系中,子类可以直接访问,父类的成员变量和方法,从而造成子类和父类方法的严重耦合。

class Base{
	public Base(){
		test();
	}
	public void test(){
		System.out.println("将被子类重写的方法");
	}
}
public class Sub {
	private String name;
	public void test(){
		System.out.println("子类重写父类的方法"+"其name字符串长度"+name.length());	
	}
	public static void main(String[] args){
		//会引发空指针异常
		Sub s=new Sub();
		System.out.println(s.name);
		s.name="asd";//在此处,如果没有设置name的值那么运行程序的时候会提示空指针异常,name的值为null,无法运行name.length()
		s.test();
	}
}
为何要派生出子类?不仅需要保证子类是一种特殊的父类,而且需要具备以下几种基本特征条件之一

1)子类需要额外增加属性,而不仅仅是属性值的改变。例如从Person类派生出Student子类,Person类里没有提供grade(年级)属性,而Student类需要grade属性来保存student对象就读的年级,这种父类到子类的派生,就符合Java继承的前提

2)子类需要增加自己独有的行为方式(包括增加新的方法或者是重写父类的方法)例如从Person类派生出的Teacher类,其中Teacher类就需要增加一个teaching()方法,该方法用于描述Teacher对象独有的行为方式:教学。

3.利用组合实现复用

class Animals{
    private void beat(){
        System.out.println("心脏跳动……");
    }
    public void breath(){
        beat();
        System.out.println("吸一口气,吐一口气,呼吸中……");
    }
}
class Bird{
    //将原来的父类组合到原来的子类,作为子类的一个组合部分
    private Animals a;
    public Bird(Animals a){
        this.a=a;
    }
    //重新定义一个自己的breath()方法
    public void breath(){
        //直接调用Animals提供breath()方法实现Bird的breath()方法
        a.breath();
    }
    public void fly(){
        System.out.println("我在天空自由地飞翔……");
    }
}
class Wolf{
    //将原来的父类组合到原来的子类中,作为子类的一个组合部分
    private Animals a;
    public Wolf(Animals a){
        this.a=a;
    }
    //重新定义一个自己的breath()方法
    public void breath(){
        a.breath();
    }
    public void run(){
        System.out.println("我在陆地上自由的奔跑……");
    }
}
public class CompositeTest {
    public static void main(String[] args){
        Animals a1=new Animals();
        Bird b=new Bird(a1);
        b.breath();
        b.fly();
        //此时需要显式地创建被组合的对象
        Animals a2=new Animals();
        Wolf w=new Wolf(a2);
        w.breath();
        w.run();
    }

}
此时的Wolf对象和Bird对象由Animals对象组合而成,因此在上面程序创建的Wolf对象和Bird对象之前创建的Animals对象,并利用这个Animals对象来创建Wolf对象和Bird对象。


猜你喜欢

转载自blog.csdn.net/xiao_chainiao/article/details/75195945
今日推荐