接口、继承与多态


 

1.类的继承



class Test {
	public Test() { // 构造方法
		//...
	}

	protected void doSomething() { // 成员方法
        //...
	}

	protected Test doIt() { // 方法返回值类型为Test类型
		return new Test();
	}
}

class Test2 extends Test { // 继承父类
	public Test2() { // 构造方法
		super(); // 调用父类构造方法
		super.doSomething(); // 调用父类成员方法
	}

	public void doSomethingnew() { // 新增方法
		// ...
	}

	public void doSomething() { // 重写父类方法
		// ...
	}

	protected Test2 doIt() { // 重写父类方法,方法返回值类型为Test2类型
		return new Test2();
	}
}

(1).子类继承父类的成员变量
 当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。原则如下:
1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量
2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承
3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

(2).子类继承父类的方法
原则:
1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;
2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;
3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。


2.Object类

Object类是所有类的父类,是Java类层中的最高层类,实质上Java中任何一个类都是它的子类。当创建一个类时,总是在继承,除非某个类已经指定要从其他类继承,否则它就是从java.lang.Object类继承而来的,如String、Integer等类都是继承于Object类;除此之外自定义的类也都继承于Object类。由于所有类都是Object子类,所以在定义类时,省略了extends Object关键字。
注意:Object类中的getClass()、notify() notifyAll() wait() 等方法不能被重写,因为这些方法被定义为final型。

常见方法:
(1)getclass() 方法
getclass() 方法是Object类定义的方法,它会返回对象执行时的Class实例。

(2)toString() 方法
package hello;

public class Main {
	public String toString() { // 重写toString()方法
		return "在" + getClass().getName() + "类中重写toString()方法";
	}
	
	public static void main(String[] args) {
		System.out.println(new Main()); // 打印本类对象
	}
}
/*输出:
在hello.Main类中重写toString()方法
*/

(3)equals()方法

package hello;

class V { // 自定义类V
	
}

public class Main {
	public static void main(String[] args) {
		String s1 = "123"; // 实例化两个对象,内容相同
		String s2 = "123";
		System.out.println(s1.equals(s2)); // 使用equals()方法调用
		V v1 = new V(); // 实例化两个V类对象
		V v2 = new V();
		System.out.println(v1.equals(v2)); // 使用equals()方法比较v1与v2对象
	}
}
/*输出:
true
false
*/

在自定义的类中用equals() 方法进行比较时,equals() 方法的默认实现是使用“==”运算符比较两个对象的引用地址。

3.对象类型的转换

(1)向上转型
package hello;

class Quadrangle { // 四边形类
	public static void draw(Quadrangle q) { // 四边形类中的方法
		// ...
	}
}

public class Parallelogram extends Quadrangle { // 平行四边形类,继承了四边形类
	public static void main(String args[]) {
		Parallelogram p = new Parallelogram(); // 实例化平行四边形类对象引用
		draw(p); // 调用父类方法 相当于Quadrangle obj=new Parallelogram();
	}
}
 
把子类对象赋值给父类类型的变量,被称为“向上转型”。

                       四边形类
                            ↑
                   平行四边形类

(2)向下转型

package hello;

class Quadrangle { // 四边形类
	public static void draw(Quadrangle q) { // 四边形类中的方法
		// ...
	}
}

public class Parallelogram extends Quadrangle { // 平行四边形类,继承了四边形类
	public static void main(String args[]) {

		draw(new Parallelogram());
		// 调用父类方法,向上转型,相当于Quadrangle obj=new Parallelogram();
		Quadrangle q = new Parallelogram();
		// 将父类对象赋予子类对象,并强制转换为子类型!!!
		Parallelogram p = (Parallelogram) q;
	}
}

将父类对象强制转换为某个子类对象,这种方式称为显示转换。

4.使用instanceof操作符判断对象类型

当程序执行向下转型操作时,如果父类对象不是子类对象,就会发生ClassCaseException异常,所以在执行向下执行之前 需要判断父类对象是否为子类对象的实例,这个判断通常使用instanceof操作符来完成。

下面创建Parallelogram类和3个内部类 Quadrangle、Square、Anything。

package hello;

class Quadrangle {
	public static void draw(Quadrangle q) {
		// ...
	}
}

class Square extends Quadrangle {
	// ...
}

class Anything {
	// ...
}

public class Parallelogram extends Quadrangle {
	public static void main(String args[]) {
		Quadrangle q = new Quadrangle(); // 实例化父类对象
		// 判断父类对象是否为Parallelogram子类的一个实例
		if (q instanceof Parallelogram) {
			Parallelogram p = (Parallelogram) q; // 向下转型操作
		}
		// 判断父类对象是否为Parallelogram子类的一个实例
		if (q instanceof Square) {
			Square s = (Square) q; // 进行向下转型操作
		}
		// 由于q对象不为Anything类的对象,所以这条语句是错误的
		// System.out.println(q instanceof Anything);
	}
}


5.方法的重载

package hello;

public class Main {
	public static int add(int a, int b) { // 定义一个方法
		return a + b;
	}

	// 定义与第一个方法相同名称、参数类型不同的方法
	public static double add(double a, double b) {
		return a + b;
	}

	public static int add(int a) { // 定义与第一个方法参数个数不同的方法
		return a;
	}

	public static int add(int a, double b) { // 定义一个成员方法
		return 1;
	}

	// 这个方法与前一个方法参数次序不同
	public static int add(double a, int b) {
		return 1;
	}

	public static void main(String args[]) {
		System.out.println("调用add(int,int)方法:" + add(1, 2));
		System.out.println("调用add(double,double)方法:" + add(2.1, 3.3));
		System.out.println("调用add(int)方法:" + add(1));
	}
}

/*
 * 输出结果: 
 * 调用add(int,int)方法:3 
 * 调用add(double,double)方法:5.4 
 * 调用add(int)方法:1
 */

编译器是利用方法名、方法各参数类型和参数的个数以及参数的顺序来确定类中的方法是否唯一。

6.多态

多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
多态存在的三个必要条件:要有继承;要有重写;父类引用指向子类对象。


package hello;

public class Quadrangle {
	// 实例化保存四边形对象的数组对象
	private Quadrangle[] qtest = new Quadrangle[6];
	private int nextIndex = 0;

	public void draw(Quadrangle q) { // 定义draw()方法,参数为四边形对象
		if (nextIndex < qtest.length) {
			qtest[nextIndex] = q;
			System.out.println(nextIndex);
			nextIndex++;
		}
	}

	public static void main(String[] args) {
		// 实例化两个四边形对象,用于调用draw()方法
		Quadrangle q = new Quadrangle();
		q.draw(new Square()); // 以正方形对象为参数调用draw()方法
		// 以平行四边形对象为参数调用draw()方法
		q.draw(new Parallelogramgle());
	}
}

class Square extends Quadrangle { // 定义一个正方形类,继承四边形类
	public Square() {
		System.out.println("正方形");
	}
}

// 定义一个平行四边形类,继承四边形类
class Parallelogramgle extends Quadrangle {
	public Parallelogramgle() {
		System.out.println("平行四边形");
	}
}



7.抽象类与接口

抽象类

package hello;

abstract class A {// 定义一个抽象类

	public void fun() {// 普通方法
		System.out.println("存在方法体的方法");
	}

	public abstract void print();// 抽象方法,没有方法体,有abstract关键字做修饰

}

// 单继承
class B extends A {// B类是抽象类的子类,是一个普通类

	public void print() {// 强制要求覆写
		System.out.println("Hello World !");
	}

}

public class Main {

	public static void main(String[] args) {
		A a = new B();// 向上转型

		a.print();// 被子类所覆写的过的方法
	}
}
/*
 * 输出: Hello World !
 */

普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。

抽象类的使用原则如下: 
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理; 
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类; 
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类
);


接口

比如说你饿了看见一家店,牌子上写着kfc,当看见kfc这个接口,我们就知道这家店卖鸡腿、汉堡。
接口是抽象类的延伸,java接口必须通过类来实现它的抽象方法,接口中的所有方法默认都是public,abstract类型的(都可省略),没有方法体,不能被实例化。

public interface drawPic //drawPic是接口名称
{
  void draw(); //接口内的方法
}
注意几点:
(1)Java接口中的成员变量默认都是public,static,final类型的(都可省略),必须被显示初始化,即接口中的成员变量为常量(大写,单词之间用"_"分隔)
(2)一个接口不能实现(implements)另一个接口,但它可以继承多个其它的接口,一个类只能继承一个直接的父类,但可以实现多个接口,间接的实现了多继承.
interface intf1 {  }
interface intf2 extends intf1 {  }
(3)当类实现了某个Java接口时,它必须实现接口中的所有抽象方法,否则这个类必须声明为抽象类
(4)不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例

package hello;

interface drawTest { // 定义接口
	public void draw(); // 定义方法
}

// 定义平行四边形类,该类继承了四边形类,并实现了drawTest接口
class ParallelogramgleUseInterface extends QuadrangleUseInterface implements
		drawTest {
	public void draw() { // 由于该类实现了接口,所以需要覆盖draw()方法
		System.out.println("平行四边形.draw()");
	}

	void doAnyThing() { // 覆盖父类方法
		// ...
	}
}

class SquareUseInterface extends QuadrangleUseInterface implements drawTest {
	public void draw() {
		System.out.println("正方形.draw()");
	}

	void doAnyThing() {
		// ...
	}
}

class AnyThingUseInterface extends QuadrangleUseInterface {
	void doAnyThing() {

	}
}

public class QuadrangleUseInterface { // 定义四边形类
	public void doAnyTthing() {
		// ...
	}

	public static void main(String[] args) {
		drawTest[] d = { // 接口也可以进行向上转型操作
		new SquareUseInterface(), new ParallelogramgleUseInterface() };
		for (int i = 0; i < d.length; i++) {
			d[i].draw(); // 调用draw()方法
		}
	}
}
/*输出结果
正方形.draw()
平行四边形.draw()
*/

用来计算每一种交通工具运行1000公里所需的时间,已知每种交通工具的参数都是3个整数A、B、C的表达式。现有两种工具:Car 和Plane,
Car 的速度运算公式为:A*B/C
Plane 的速度运算公式为:A+B+C。
如果增加第3种交通工具的时候,比如火车(Train)不必修改以前的任何程序,只需要编写新的交通工具的程序。

package hello;

interface Common {
	double runTimer(double a, double b, double c);

	String getName(); // 获取交通工具的名称
}

class Plane implements Common {
	public double runTimer(double a, double b, double c) {
		return (a + b + c);
	}

	public String getName() {
		return "Plane";
	}
}

class Car implements Common {
	public double runTimer(double a, double b, double c) {
		return (a * b / c);
	}

	public String getName() {
		return "Car";
	}
}

public class Main {

	public static void main(String args[]) {
		double A = 3;
		double B = 5;
		double C = 6;
		double v, t;
		Common d = new Car();
		v = d.runTimer(A, B, C);
		t = 1000 / v;
		System.out.println(d.getName() + "的平均速度: " + v + " km/h");
		System.out.println(d.getName() + "的运行时间:" + t + " 小时");
		d = new Plane();
		v = d.runTimer(10, 30, 40);
		t = 1000 / v;
		System.out.println(d.getName() + "的平均速度: " + v + " km/h");
		System.out.println(d.getName() + "的运行时间:" + t + " 小时");
	}
}
/*输出结果
Car的平均速度: 2.5 km/h
Car的运行时间:400.0 小时
Plane的平均速度: 80.0 km/h
Plane的运行时间:12.5 小时
*/






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值