JAVA基础(一):面向对象之接口与继承以及子类父类的相互转换

面向对象的编程思想,通过将现实世界的

个体种类抽象成(class),

单个个体抽象成对象(object),

种类与种类之间的关系抽象成继承(inheritance),

使开发人员能够以符合正常思维的方式进行程序设计,提高编程效率。


Java语言中,继承关系的描述可以通过

实现接口(interface),

继承父类(superClass)以及抽象类(abstractClass)

来完成。当某个类继承父类时,即可调用父类的非私有方法;由于接口的实现类,对接口方法的描述可能不一样,因此接口只作方法的声明,具体内容必须要在接口的实现类中定义(接口理解起来更像是对实现类应该包含内容的规定)。为了避免多重继承造成的混乱,Java通过单继承与多重接口,即一个子类有且仅有一个父类(默认继承Object类,Object类没有父类),但可以通过实现多个接口,来完成类自身的描述。


开发过程中,经常涉及到类型的强制转换。首先我们要理解的是,宏观上来说,构造一个对象的过程,例如,String ref1 = new String("abc"),可以分为两个步骤。

首先,通过new String("abc")在内存中新建一块区域,来存放我们的这个对象;

然后通过引用ref1来“指向”内存中的这个对象,以调用对象的方法。

而强制转换的过程,例如Object ref2 = (Object) ref1,可以理解为让Object类的引用ref2也指向ref1所指向的空间,之后便通过ref2的类型(Object类)来调用内存中对象的方法。

--------------------------------------------------------------------------------------------------------

概念介绍完了,下面通过一个简单的demo来作分析:

  Son类继承自Father,是Father类的子类,Father是Son的父类;同时,Father和Son类都属于人类,都实现了Person接口。

  Father养家需要工作,有一个work方法;Son以学习为主,有一个study方法,且由于Son类继承了Father类,所以Son类下的对象也拥有Father类下的work方法;每个Person都会介绍自己,因此Person接口中声明了一个introduce方法。

  tom和jim这两个Person是Father和Son的关系。tom是jim的父亲,是Father类下的一个对象;jim是tom的儿子,是Son类下的一个对象。


Person接口:

public interface Person {
	// 介绍自己的方法
	public void introduce();
}

Person接口只是声明了introduce方法,方法的具体内容要在其实现类中描述。

Father类:

public class Father implements Person {
	// Father个体的名字
	private String name;
	// 此处进通过构造函数来初始化姓名
	public Father(String name) {
		this.name = name;
	}
	// 实现Person接口的introduce方法
	public void introduce() {
		System.out.println("Father name is :  " + name);
	}
	// Father个体需要work()来养家
	public void work() {
		System.out.println(name + " works for family!");
	}
	// Java三大特性之:封装。其他个体不能随意修改别人的名字
	public String getName() {
		return name;
	}
}

Father类实现了Person接口,定义introduce方法,打印了一行信息:Father name is + 自己的名字。同时定义了work方法,打印了一行信息:name + works for family!。

Son类:

public class Son extends Father implements Person{
	// Son个体的名字
	private String name;
	// Son的构造方法中,通过super()调用Father父类的构造方法
	public Son(String name) {
		super("my son's name is " + name);
		this.name = name;
	}
	// Son中实现Person接口的introduce方法
	public void introduce() {
		System.out.println("Son name is :  " + name);
	}
	// Son个体的使命是study()
	public void study() {
		System.out.println(name + " is studying!");
	}

	public String getName() {
		return name;
	}
}

Son类继承了Father类,自身定义了study方法,打印一行信息:name + is studying!;Son类同时实现了Person接口,定义introduce方法,打印了一行信息:Son name is + name。Son类的构造方法中,通过super()为将一条字符串传入到了父类的构造函数中。

--------------------------------------------------------------------------------------------------------

接下来作如下测试:

1. 构造Father类对象tom,Son类对象jim,分别调用各自的方法。

2. 通过Person引用Father类的tom对象和Son类的jim对象(因为Father类和Son类都实现了Person接口,否则编译会报错“类型无法转换”),并尝试调用各自的方法。

3. 尝试将Father类对象tom和Son类对象jim互相转换,并调用各自的方法。

测试类Main:

public class Main {

	public static void main(String[] args) {
		test1();
		test2();
		test3();
	}

	public static void test1() {
		System.out.println("*****************TEST1*****************");
		Father tom = new Father("Tom");
		Son jim = new Son("Jim");
		// 调用Person接口的introduce方法来介绍自己
		tom.introduce();
		jim.introduce();
		// 调用tom和jim各自的方法
		tom.work();
		jim.study();
		jim.work(); // Son类继承了Father类,因此Son对象jim也有work方法
	}

	public static void test2() {
		System.out.println("*****************TEST2*****************");
		// 通过Person接口引用Father类和Son类的具体实现
		Person tom = new Father("Tom");
		Person jim = new Son("Jim");
		// 分别打印tom和jim实现类的类名。具体细节之后的篇幅再解释
		System.out.println("Person tom's class name :");
		System.out.println(tom.getClass().getName());
		System.out.println("Person jim's class name :");
		System.out.println(jim.getClass().getName());

		tom.introduce();
		jim.introduce();
		// 由于Person接口中没有方法的声明,编译时报错method undefined
//		tom.farm(); 
//		jim.recite();
//		jim.farm();
		// tom的具体实现类是Father类,因此强制转换tom对象后可以调用work()
		((Father)tom).work();
		((Son)jim).study(); // jim同理
		((Son)jim).work();
	}

	public static void test3() {
		System.out.println("*****************TEST3*****************");
		// 父类不能强制转换成子类,运行时报异常 cannot be cast to
//		Son s = (Son)new Father("Tom");
		Father tom = new Father("Tom");
		Father jim = new Son("Jim");

		/* 和test2中一样,通过Father引用Son的对象来调用Son类特有的study方法
		 * 编译时会提示method undefined
		 */
//		jim.study();
		// 通过强制转换,将Son类向上转换
		((Son)jim).study();
		jim.work();
		// 将jim强制转换为Son类型后,调用相应的方法
		((Son)jim).work();
		((Son)jim).introduce();
		jim.introduce();
		((Person)jim).introduce();
		// 同理,将tom对象通过Persson接口引用,也能够调用Person接口中声明了的方法
		((Person)tom).introduce();
		// 而将tom向下转换,通过Son来引用,虽然编译能够通过,但运行时会抛出异常 cannot be cast
//		((Son)tom).work();
	}
}

运行结果:

test1中,由于Son类继承了Father类,所以jim对象能够调用父类的work方法,打印了在构造函数中传给父类构造函数的name信息。

test2中,通过定义的两个Person引用,tom和jim,分别指向了Father类对象和Son类对象,调用了在Person接口中声明了的introduce方法;但如果通过Person引用直接调用Father类或Son类下的其他方法时,则编译报错method undefined,加上强制转换,通过Father引用和Son引用,即可调用相应的方法。同时,通过打印出的实现类信息中也可以看出,Person tom的具体实现类是Father类,Person jim的具体实现类是Son类。

test3中,通过打印出的信息可以看出,不论jim对象怎么向上转换,调用introduce()和work()方法时打印的信息都是相同的,也说明了调用的方法只和具体实现类有关,不会受到强制转换(更换引用)的影响。而tom对象是Father类的实现,当将其向下转换成Son类对象(通过Son引用)时,运行时会抛出ClassCastException。

--------------------------------------------------------------------------------------------------------

java中,每个类的定义也是一个对象,是Class类的对象,通过Class类,可以打印出具体类对象的信息,涉及到反射(reflect)的相关知识。

子类对象能够强制向上转换,而父类对象不能强制向下转换。简单的来说,因为子类对象中包含了父类的所有内容,父类引用时可以忽略这部分子类中多余的内容来正常调用;但父类对象中可能缺少子类的相关信息,因此转换后编译会不通过。

这些个内容等之后研究到具体的案例再作分析吧。


第一次写blog,只是把自己认为相关联的东西记在一起,可能内容比较杂乱,嘿嘿。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值