Java面向对象_8.Java多态(2)

一、抽象方法

1、注意

(1)抽象方法不允许有方法体,要用分号结束
(2)子类中需要重写父类的抽象方法
(3)将子类变为抽象类时可以不重写父类抽象方法

2、作用

提醒子类重写父类的抽象方法

3、使用规则

(1)abstract定义抽象类
(2)抽象类不能直接实例化,只能被继承,可以通过向上转型完成对象的实例
(3)abstract定义抽象方法,不需要具体实现
(4)包含抽象方法的类一定是抽象类
(5)抽象类中可以没有抽象方法
(6)static final private 都不可与abstract同用

4、Java中只支持单继承

子类------------------>唯一父类

二、接口

1、如何解决一个类型中需要兼容多种类型特征的问题?以及多个不同类型具有相同特征的问题?

例如:
四代手机–extends–>三代手机–extends–>二代手机–extends–>一代手机
相机、电脑、智能手表、四代手机 都具有某些相同特征。

2、接口是什么

(1)接口定义了某一批类所需要遵守的规范
(2)接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法

3.在java中,一个类可以实现多个接口

当四代手机—> extends 三代手机,implements INet、IPhoto时
都有同名的connection方法,此时会指向父类中的同名方法。

4.代码实现

package com.study.tel;

/**
 * 原始手机
 * 
 * @author l1
 *
 */
public class Telphone {
	private String brand;
	private int price;

	public Telphone() {

	}

	// 打电话
	public void call() {
		System.out.println("手机可以打电话");
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}
}

package com.study.tel;

public class SecondPhone extends Telphone {
	public void message() {
		System.out.println("手机可以发短信");
	}
}

package com.study.tel;

public class ThirdPhone extends SecondPhone {
	public void vedio() {
		System.out.println("手机可以看视频");
	}

	public void music() {
		System.out.println("手机可以听音乐");
	}

	public void connection() {
		System.out.println("三代手机中的连接");
	}
}

package com.study.tel;

public class FourthPhone extends ThirdPhone implements IPhoto, INet {

	public void network() {
		System.out.println("手机可以上网");
	}

	public void game() {
		System.out.println("手机可以玩游戏");
	}

	@Override
	public void photo() {
		System.out.println("手机可以拍照");
	}
}

package com.study.tel;

public class Camera implements IPhoto{

	@Override
	public void photo() {
		System.out.println("相机可以拍照");
	}


}

package com.study.tel;

public abstract class Computer implements INet {
	
	public void game() {
		System.out.println("电脑可以玩游戏");
	}

	public void vedio() {
		System.out.println("电脑可以看视频");
	}

	public void call() {
		System.out.println("电脑可以打电话");
	}

	@Override
	public void network() {
		// TODO Auto-generated method stub
		System.out.println("电脑可以上网");
	}
}

package com.study.tel;

public class SmartWatch implements INet, IPhoto {

	public static final int TEMP = 30;

	public void network() {
		System.out.println("智能手表可以上网");
	}

	public void call() {
		System.out.println("智能手表可以打电话");
	}

	public void message() {
		System.out.println("智能手表可以发短信");
	}

	@Override
	public void photo() {
		// TODO Auto-generated method stub
	}
	
	public void connection() {
		System.out.println("SmartWatch中的connection");
	}
}

package com.study.tel;

//接口访问修饰符:public  默认
public interface INet {
	// 接口中抽象方法可以不写abstra关键字,会默认为抽象方法
	// 也可以不写public,会默认为public
	// 当一个类实现接口时,需要去实现接口中的所有抽象方法,否则需要将该类设置为抽象类
	void network();

	// 接口中可以包含常量,默认public static final
	int TEMP = 20;

	// default:默认方法 可以带方法体 可以不用在实现类中实现 jdk1.8后新增
	// 可以在实现类中重写,并可以通过接口的引用调用
	default void connection() {
		System.out.println("接口中的默认连接");
	}

	// static:静态方法 可以带方法体 可以不在实现类中实现 jdk1.8后新增
	// 不可以在实现类中重写,可以通过接口名调用
	static void stop() {
		System.out.println("接口中的静态方法");
	}
}

package com.study.tel;

/**
 * 具有照相能力的接口
 * 
 * @author l1
 *
 */
public interface IPhoto {
	// 具有拍照的能力
	public void photo();

	default void connection() {
		System.out.println("IPhoto中的connection");
	}
}

package com.study.test;

import com.study.tel.Camera;
import com.study.tel.FourthPhone;
import com.study.tel.INet;
import com.study.tel.IPhoto;
import com.study.tel.SmartWatch;

public class PhoneTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FourthPhone phone = new FourthPhone();
		phone.call();
		phone.message();
		phone.vedio();
		phone.music();
		phone.photo();
		phone.network();

		System.out.println("=============");
		IPhoto ip = new FourthPhone();
		ip.photo();
		ip = new Camera();
		ip.photo();
		System.out.println(INet.TEMP);
		INet net = new SmartWatch();
		System.out.println(net.TEMP);// 实现类中存在和接口同名信息,打印的是接口中的常量 20
		net.connection();
		INet.stop();

		SmartWatch sw = new SmartWatch();
		System.out.println(sw.TEMP);// 30

		INet net2 = new SmartWatch();
		net2.connection();
		IPhoto ip2 = new SmartWatch();
		ip2.connection();

		System.out.println("===========");
		INet net3 = new FourthPhone();
		net3.connection();
		IPhoto ip3 = new FourthPhone();
		ip3.connection();
	}

}

输出:

手机可以打电话
手机可以发短信
手机可以看视频
手机可以听音乐
手机可以拍照
手机可以上网
=============
手机可以拍照
相机可以拍照
20
20
SmartWatch中的connection
接口中的静态方法
30
SmartWatch中的connection
SmartWatch中的connection
===========
三代手机中的连接
三代手机中的连接

5.同名属性

(1)

interface One{
	static int x = 11;
}
interface Two{
	final int x = 22;
}
class Three(){
	public int x = 33;
}

public class TestOne implements One,Two{
	public void test(){
		System.out.println(x);//报错,不知道访问哪个接口中的x,
		//应改为One.x或Two.x
	}
	public static void main(String[] args){
		new TestOne().test();
	}
}

(2)

interface One{
	static int x = 11;
}
interface Two{
	final int x = 22;
}
class Three(){
	public int x = 33;
}

public class TestTwo extends Three implements One,Two{
	public void test(){
		System.out.println(x);//报错,常量同名时无法分辨x
	}
	public static void main(String[] args){
		new TestOne().test();
	}
}

(3)

interface One{
	static int x = 11;
}
interface Two{
	final int x = 22;
}
class Three(){
	public int x = 33;
}

public class TestThree extends Three implements One,Two{
	public int x = 44;
	public void test(){
		System.out.println(x);//无错误,输出44
	}
	public static void main(String[] args){
		new TestOne().test();
	}
}

6.接口中的继承

interface IFather{
	void say();
}
interface IFather2{
	void dance();
}
interface ISon extends IFather,IFather2{
	void run();
}
public class Test implements ISon{
	public void say(){
	
	}
	public void run(){
	
	}
	public void dance(){
	
	}
}

子类继承 :唯一父类
子接口继承 : 多个父接口

7.注意

(1)接口也可以实现继承,并且可以继承多个接口
(2)此时若两个父接口中有默认同名方法,子接口会报错,无法分辨。只能创建属于自己的同名方法

三、内部类

1.在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类,包含内部类的类称为外部类

public class Person{
	int age;
	public Heart getHeart(){
		return new Heart();
	}
	class Heart{
		public String beat(){
			return "心脏在跳动";
		}	
	}
}

2.作用

内部类隐藏在外部类之内,更好的实现了信息隐藏

3.分类

成员内部类、静态内部类、方法内部类、匿名内部类

四、成员内部类(普通内部类)

1.实现

public class Person{
	int age;
	public Heart getHeart(){
		return new Heart();
	}
	class Heart{
		public String beat(){
			return "心脏在跳动";
		}	
	}
}

2.实例:

同包下:

public class PeopleTest{
	public static void main(String []args){
		Person lili = new Person();
		lili.age = 12;
		Heart myHeart = new Heart();//报错
		//方式一:new 外部类.new 内部类
		Person.Heart myHeart = new Person().new Heart();
		System.out.println(myHeart.beat());
		//方式二:外部类对象.new 内部类
		myHeart = lili.new Heart();
		//方式三:外部类对象.获取方法
		myHeart = lili.getHeart();
	}
}

(1)内部类在外部使用时,无法直接实例化,需要借用外部类信息才能完成实例化
(2)内部类访问修饰符会影响访问范围
(3)内部类可以直接访问外部类的成员,若内部类、外部类用同名的变量age/方法,则内部类访问的是内部类中的变量age/方法
优先访问内部类中定义的成员
(4)Person.this.age可以使用外部类.this.成员的方法访问外部类中同名的信息
(5)存储位置
bin-com-study-people-people-Person.class/Person$Heart.class

3.注意

(1)外部类中使用内部类成员:new Heart.temp = 12;
(2)外部类访问内部类信息,需要通过内部类实例,无法直接访问
(3)内部类编译后,文件命名:
外部类$内部类.class

五、静态内部类

1.静态内部类对象可以不依赖于外部类对象,直接创建。

public class Person{
	int age;
	public Heart getHeart(){
		return new Heart();
	}
	static class Heart{
		public String beat(){
			return "心脏在跳动";
		}	
	}
}

静态类只能调用静态方法
(1)静态内部类中只能直接访问外部类的静态成员,如果需要调用非静态成员可以通过对象实例。
new Person().eat()
new Person().age

2.实例

Person.Heart myHeart = new Person.Heart();
System.out.println(myHeart.beat());

3.静态内部类中静态成员

public class Person{
	int age;
	public Heart getHeart(){
		return new Heart();
	}
	static class Heart{
		public static int age = 13;
		public static void says(){
			System.out.println("人会说话");
		}
		public String beat(){
			return "心脏在跳动";
		}	
		Person.Heart.age = 12;
		Person.Heart.say();
	}
}

(1)静态内部类对象实例时,可以不依赖于外部类对象
(2)可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
(3)当内部类属性与外部类属性同名时,默认直接调用内部类中的成员,如果需要访问外部类中的静态属性,则可以通过外部类.属性方式
(4)如果需要访问外部类中的非静态属性,可以通过new 外部类.属性方式

六、方法内部类(局部内部类)

1.定义在外部类方法中的内部类,也称局部内部类。

(1)方法内定义的局部变量只能在方法里使用
(2)方法内不能定义静态成员
(3)不能用public等访问修饰符修饰

2.实现

public class Person{
	int age;
	public Object getHeart(){
		class Heart{
			public static int age = 13;
			public static void says(){
				System.out.println("人会说话");
			}
			public String beat(){
				return "心脏在跳动";
			}	
			Person.Heart.age = 12;
			Person.Heart.say();
		}
		return new Heart().beat();
	}
}

3.实例对象

Person lili = new Person();
System.out.println(lili.getHeart());

4.存储文件

bin-com-study-people-Person.class/person$1Heart.class

5.注意

(1)定义在方法内部,作用范围也在方法内
(2)和方法内部成员使用规则一样,class前不能加public、private、protected、static关键字
(3)类中不能包含静态成员,但可以包括final成员或(不推荐)abstract方法且类也为抽象

七、匿名内部类

1.当只使用一次的类时,将类的定义与类的创建放在一起完成

2.代码实现

package com.study.anonymous
public abstract class Person{
	private String name;
	public Person(){
	
	}
	public String getName(){
		return this.name;
	}
	public void setName(String name){
		this.name = name;	
	}
}
public class Man extends Person{
	public void read(){
		System.out.println("男生爱看科幻书");
	}
}
public class Woman extends Person{
	public void read(){
		System.out.println("女生爱看言情书");
	}
}
public class PersonTest{
	//方案一:
	public void getRead(Man man){
		man.read();
	}
	public void getRead(Woman woman){
		woman.read();
	}
	public static void main(String[] args){
		PersonTest test = new PersonTest();
		Man one = new Man();
		Woman two = new Woman();
		test.getRead(one);
		test.getRead(two);
	}
	//方案二:
	public void getRead(Person person){
		person.read();
	}
	//匿名内部类:
	test.getRead(new Person(){
		public void read(){
			System.out.println("男生爱看科幻书");
		}
	});
	test.getRead(new Person(){
		public void read(){
			System.out.println("女生爱看言情书");
		}
	});
}

3.适用场景

(1)只用到类的一个实例
(2)类在定义后马上用到
(3)给类命名不会导致代码更容易被理解

4.存储文件

bin-com-study-test-

PersonTest.class
PersonTest$1.class
PersonTest$2.class

5.注意

(1)匿名内部类没有类型名称、实例对象名称
(2)编译后文件命名:外部类$数字.class
(3)无法使用private、public、protected、abstract、static修饰
(4)无法编写构造方法,可以用构造代码块初始化
(5)不能出现静态成员
(6)匿名内部类可以实现接口也可以继承父类,但是不可兼得。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值