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)匿名内部类可以实现接口也可以继承父类,但是不可兼得。