接口 (接口定的功能是额外扩展的功能——扩展性)
关键字interface
当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类使用另一种形式定义和表示,就是接口interface
接口的特点:
1 / 接口用interface关键字定义(不用class)
格式:interface 接口名 { }
2 / 类实现接口用implements 表示
格式: class 类名 implements 接口名 { }
3 / 接口不能实例化
按照多态的方式来实例化。
4 / 接口的子类
a / 可以是抽象类,但是没意义。
b / 可以是具体类。要重写接口中的所有抽象方法。
范例:
//定义动物培训接口
interface AnimalTrain
{
public abstract void jump();
}
//抽象类实现接口,但是没有意义
abstract class Dog implements AnimalTrain
{
}
//具体类实现接口,需要重写抽象方法
class Cat implements AnimalTrain
{
public void jump()
{
System.out.println("猫可以跳高");
}
}
class InterfaceDemo_01
{
public static void main(String[] args)
{
AnimalTrain c = new Cat();
c.jump();
}
}
接口的成员特点:
1 / 成员变量
---| 接口中的变量,默认是常量,并且是静态的。有默认修饰符:public static final
2 / 构造方法
---| 接口没有构造方法。
3 / 成员方法
---| 接口方法没有方法体。是一个抽象方法。默认 public abstract
类与类,类与接口,接口与接口的关系:
类与类之间是继承关系,只能单继承,可以多层集成。
类与接口之间是实现关系,可以单实现,也可以多实现。并且还可以在继承一个类的同时实现多接口。对应的接口调用对应方法。
接口与接口直接是继承关系,可以单继承也可以多继承。
一个类实现一个接口,要想实例化,必须覆盖所有方法。
范例:
/*
各种关系:
类与类:
类与接口:
接口与接口:
*/
interface Father //定义一个Father接口
{
public abstract void show(); //接口中的方法必须是抽象方法(没有方法体)
}
interface Mother //定义一个Mother接口
{
public abstract void show2(); //接口中的方法必须是抽象方法(没有方法体)
}
class Son extends Object implements Father,Mother //定义一个Son类,继承一个类(Object)的同时实现多接口(Father,Mother)
{
public void show() //重写Father类中的抽象方法
{
System.out.println("show son");
}
public void show2() //重写Mother类中的抽象方法
{
System.out.println("show2 son");
}
}
interface Sister extends Father,Mother //定义一个Sister接口,多继承Father,Mother
{
}
class Brother implements Sister //定义一个brother类,实现Sister接口
{
public void show() //重写Sister接口中的抽象方法
{
System.out.println("show brother");
}
public void show2() //重写Sister接口中的抽象方法
{
System.out.println("show2 brother");
}
}
class InterfaceDemo_02
{
public static void main(String[] args)
{
Father f = new Son();
f.show();
Mother m = new Son();
m.show2();
Sister s = new Brother();
s.show();
s.show2();
}
}
接口中的成员都是公共的权限。
1/抽象方法 public abstract
2/全局常量 public stratic final
class InterfaceDemo
{
public static void main(String[] args)
{
DemoImp1 d = new DemoImp1();
System.out.println(d.NUM); //三种方式都是正确的
System.out.println(DemoImp1.NUM);
System.out.println(Demo.NUM);
}
}
interface Demo
{
public static final int NUM = 4; //接口中的成员必须是全局常亮和抽象方法
public abstract void show1();
public abstract void show2();
}
//类与类之间是继承关系,类与接口之间是实现关系
/*
接口不可以实例化
只能由实现了接口的子类覆盖了接口中所有的抽象方法后,该子类才可以实例化。
否则,这个子类就是一个抽象类
*/
class DemoImp1 implements Demo //一个类实现一个接口,想要实例化,必须覆盖所有方法
{
public void show1()
{
}
public void show2()
{
}
}
接口的多实现
在Java中不直接支持多继承,因为会出现调用的不确定性。
所以Java中多继承机制进行改良,在java中变成了多实现。
一个类可以实现多个接口。
interface A
{
public abstract void show();
}
interface Z
{
public abstract void show();
}
class Test implements A,Z //一个类实现多个接口
{
public void show()
{
}
}
继承+多接口
一个类在继承另一个类的同时,还可以实现多个接口
接口的出现,避免了单继承的局限性。
示例1:
interface A
{
public abstract void show();
}
interface Z
{
public abstract void show();
}
class Q
{
public void method()
{
}
}
class Test2 extends Q implements A,Z //继承了一个类,然后多实现
{
}
interface CC
{
public abstract void show();
}
interface MM
{
public abstract void method();
}
interface QQ extends CC,MM //接口与接口之间是继承关系,而且可以多继承
{
void function();
}
class WW implements QQ //类实现一个经过多继承的接口时,要全覆盖它所继承的抽象方法
{
public void show() {}
public void method(){}
public void function(){}
}
接口的特点:
1/接口是对外暴露的规则
2/接口是程序的功能扩展
3/接口的出现降低耦合性
4/接口可以用来多实现
5/类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
6/接口与接口之间可以有继承关系
抽象类和接口的区别:
A : 成员区别:
抽象类:
-----|成员变量:可以变量,也可以常量
-----|构造方法:有
-----|成员方法:可以抽象,也可以非抽象
接口:
-----|成员变量:只可以常量
-----|构造方法:无
-----|成员方法:只可以抽象
B:关系区别:
类与类:继承,单继承
类与接口:实现,单实现,多实现
接口与接口:继承,单继承,多继承
C :设计理念的区别:
抽象类:被继承体现的是:“is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口:被实现体现的是:“like a”的关系。接口中定义的是该继承体系的扩展功能。
抽象类与接口的异同点:
相同点:
1/都是不断向上抽取而来。
2/描述都不够具体
不同点:
1/抽象类需要被继承,而且只能单继承。接口需要被实现,而且可以多实现。
2/抽象类中可以定义抽象方法和非抽象方法,子类继承后可以直接使用非抽象方法
接口中只能定义非抽象方法,必须由子类去实现。
3/抽象类的继承是is a 关系,在定义该体系的基本共性内容。
接口的实现是like a 关系(像,相似)。在定义体系的额外功能。
练习案例01:
猫狗案例,加入跳高的额外功能
/*
猫狗案例,加入跳高的额外功能
分析:
猫:姓名,年龄,吃饭,睡觉
狗:姓名,年龄,吃饭,睡觉
由于有共性的功能,可以抽取出一个父类Animal
Animal:
姓名,年龄
吃饭();
睡觉()
猫类:继承Animal
狗类:继承Animal
跳高的功能:
是一个新的扩展功能,定义一个跳高的接口
部分狗:实现跳高
*/
abstract class Animal //定义一个共性的父类Animal
{
private String name;
private int age;
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
public abstract void eat();
public abstract void sleep();
}
class Cat extends Animal //定义一个cat类继承Animal
{
public void eat()
{
System.out.println("小猫吃鱼");
}
public void sleep()
{
System.out.println("小猫躺着睡觉");
}
}
class Dog extends Animal //定义一个dog类继承animal
{
public void eat()
{
System.out.println("小狗啃骨头");
}
public void sleep()
{
System.out.println("小狗站着睡觉");
}
}
interface Jump //定义一个jump接口
{
public abstract void jump();
}
class JumpDog extends Dog implements Jump //定义一个跳高狗,继承Dog,实现Jump接口
{
public void jump()
{
System.out.println("小狗跳高");
}
}
class InterfaceTest_01
{
public static void main(String[] args)
{
Animal c = new Cat();
c.setName("小花花");
c.setAge(2);
System.out.println(c.getName()+"----"+c.getAge());
c.eat();
c.sleep();
System.out.println("-----------------");
JumpDog d = new JumpDog(); //定义跳高狗对象
d.setName("大狼狗");
d.setAge(3);
System.out.println(d.getName()+"----"+d.getAge());
d.eat();
d.sleep();
d.jump();
}
}
/*
练习:老师和学生,部分抽烟
分析:
具体的:
老师:姓名,年龄,吃饭,睡觉,教书
学生:姓名,年龄,吃饭,睡觉,学习
由于有共性功能,抽取成一个Person父类
person:
姓名,年龄
吃饭();
睡觉(){}
一部分人抽烟,且不是一开始具备的功能,所以定义一个借口
smoking
部分老师抽烟:实现抽烟接口
部分学生抽烟:实现抽烟接口
*/
abstract class Person //定义一个共性的person类
{
private String name;
private int age;
public Person()
{
}
public Person(String name, int age) //使用带参构造方法
{
this.name = name;
this.age = age;
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.name = name;
}
public int getAge()
{
return age;
}
public abstract void eat();
public void sleep()
{
System.out.println("关灯睡觉");
}
}
class Student extends Person //定义一个基本学生类
{
public Student()
{
}
public Student(String name, int age) //使用带参构造方法,super自父类
{
super(name,age);
}
public void eat()
{
System.out.println("吃学校食堂");
}
public void study()
{
System.out.println("努力读书");
}
}
class Teacher extends Person //定义一个基本老师类
{
public Teacher()
{
}
public Teacher(String name, int age)
{
super(name,age);
}
public void eat()
{
System.out.println("回家做饭吃");
}
public void teach()
{
System.out.println("认真教学");
}
}
interface Smoking
{
public abstract void smok();
}
class SmokStudent extends Student implements Smoking //定义一个抽烟学生类,继承学生类,实现抽烟接口
{
public SmokStudent()
{
}
public SmokStudent(String name, int age)
{
super(name,age);
}
public void smok()
{
System.out.println("抽烟的学生");
}
}
class SmokTeacher extends Teacher implements Smoking //定义一个抽烟老师类,继承老师类,实现抽烟接口
{
public SmokTeacher()
{
}
public SmokTeacher(String name, int age)
{
super(name,age);
}
public void smok()
{
System.out.println("抽烟的老师");
}
}
class InterfaceTest_02
{
public static void main(String[] args)
{
SmokTeacher st = new SmokTeacher("大长今",26);
System.out.println(st.getName()+"----"+st.getAge());
st.eat();
st.sleep();
st.teach();
st.smok();
System.out.println("------------------------------");
SmokStudent ss = new SmokStudent("张小毛",19);
System.out.println(ss.getName()+"----"+ss.getAge());
ss.eat();
ss.sleep();
ss.study();
ss.smok();
}
}
/*
教练和运动员案例
--|乒乓球运动员和篮球运动员
--|乒乓球教练和篮球教练
--|为了出国交流,跟乒乓球相关的人员都要学习英语。
分析:
具体:
乒乓球运动员:姓名,年龄,乒乓球比赛
篮球运动员:姓名,年龄,篮球比赛
乒乓球教练:姓名,年龄,乒乓球指导
篮球教练:姓名,年龄,篮球指导
由于有些共性,所以抽取出一个父类Person
共性:
姓名
年龄
运动员的共性:比赛
教练的共性:指导
乒乓球运动员特有功能:乒乓球比赛
篮球运动员特有功能:篮球比赛
乒乓球教练特有功能:乒乓球指导
篮球教练特有功能:篮球指导
一部分人需要出国所以学习英语,定义一个学习英语的接口
*/
//定义一个Person父类,抽取共性
abstract class Person
{
private String name;
private int age;
public Person()
{
}
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public void setName(String name)
{
this.name =name;
}
public String getName()
{
return name;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
}
//定义运动员比赛共性的父类Match,继承Person
abstract class Match extends Person
{
public Match(String name, int age)
{
super(name,age);
}
public abstract void match(); //定义一个比赛的抽象方法
}
//定义教练指导共性的父类Coach,继承Person
abstract class Coach extends Person
{
public Coach(String name, int age)
{
super(name,age);
}
public abstract void coach(); //定义一个指导的抽象方法
}
//定义一个学习英语的接口
interface StudyEglish
{
public abstract void study(); //接口中的方法必须为抽象方法
}
//定义乒乓球运动员继承运动员比赛父类(多层继承Person),同时实现学习英语的接口
class TablePlayer extends Match implements StudyEglish
{
public TablePlayer(String name, int age)
{
super(name,age);
}
public void match()
{
System.out.println("乒乓球打比赛");
}
public void study()
{
System.out.println("学习英语");
}
}
//定义篮球运动员继承运动员比赛父类(多层继承Person)
class BasketballPlayer extends Match
{
public BasketballPlayer(String name, int age)
{
super(name,age);
}
public void match()
{
System.out.println("篮球打比赛");
}
}
//定义乒乓球教练继承指导父类(多层继承Person),同时实现学习英语接口
class TableCoach extends Coach implements StudyEglish
{
public TableCoach(String name, int age)
{
super(name,age);
}
public void coach()
{
System.out.println("指导如何打乒乓球");
}
public void study()
{
System.out.println("学习英语");
}
}
//定义篮球教练继承指导父类(多层继承Person)
class BasketballCoach extends Coach
{
public BasketballCoach(String name, int age)
{
super(name,age);
}
public void coach()
{
System.out.println("指导如何打篮球");
}
}
class InterfaceTest_03
{
public static void main(String[] args)
{
TablePlayer tp = new TablePlayer("李小双",20);
System.out.println(tp.getName()+"-----"+tp.getAge());
tp.match();
tp.study();
System.out.println("------------------------");
BasketballPlayer bp = new BasketballPlayer("巴贝尔",26);
System.out.println(bp.getName()+"-----"+bp.getAge());
bp.match();
System.out.println("-------------------------");
TableCoach tc = new TableCoach("邓亚萍",45);
System.out.println(tc.getName()+"-----"+tc.getAge());
tc.coach();
tc.study();
System.out.println("--------------------------");
BasketballCoach bc = new BasketballCoach("汪小晓",40);
System.out.println(bc.getName()+"-----"+bc.getAge());
bc.coach();
}
}
——————————————————————————————————————————————
引用类型作为形式参数
形式参数:
---|基本类型
---|引用类型
---------| 类作为形参,需要的是一个对象。
---------| 抽象类作为形参:一个方法的形参是一个抽象类,实际需要的是该抽象类的子类对象。
---------| 接口作为形参:一个方法的形参是接口类,实际需要的是该接口的实现类对象。
范例01:(类作为形参)
/*
一个方法的形参是类名
实际需要的是该类的对象
*/
class Student
{
public void study()
{
System.out.println("Good Good Study, Day Day Up");
}
}
class StudentDemo
{
public void method(Student s) //方法的形参是类名,实际需要的是该类的对象
{
s.study();
}
}
class ClassDemo_01
{
public static void main(String[] args)
{
//需求:要测试StudentDemo类中的method()方法
StudentDemo sd = new StudentDemo();
Student ss = new Student(); ////方法的形参是类名,实际需要的是该类的对象
sd.method(ss);
}
}
范例02:(抽象类作为形参)
/*
一个方法的形参是抽象类
实际需要的是该抽象类的子类对象。
*/
abstract class Person //定义一个抽象类
{
public abstract void study(); //抽象类中的抽象方法
}
class PersonDemo
{
public void method(Person p) //此类中的方法形参是抽象类 p = new Student(); 于是相当于 Person p = new Student();//多态
{
p.study();
}
}
//定义一个具体的学生类继承Person抽象类
class Student extends Person
{
public void study() //重写抽象类Person中的方法
{
System.out.println("Good Good Study,Day Day Up");
}
}
class
{
public static void main(String[] args)
{
//需求:要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo(); //要使用PersonDemo中的方法,需要定义此方法的对象
Person p =new Student(); //通过Person抽象类的实例化子类Student来进行多态,创建子类对象。
pd.method(p); //p = new Student(); 于是相当于 Person p = new Student();//多态
}
}
/*
一个方法的形参是接口类型
需要的是该接口的实现类对象。
*/
//定义一个爱好的接口
interface Love
{
public abstract void love();
}
class LoveDemo
{
public void method(Love l) //l = new Teacher(); Love 1 = new Teacher(); // 多态
{
l.love();
}
}
//定义一个具体类,实现接口
class Teacher implements Love
{
public void love() //重写接口中的方法
{
System.out.println("老师爱学生");
}
}
class InterfaceDemo_01
{
public static void main(String[] args)
{
//需求:要测试LoveDemo类中的method()方法
LoveDemo ld = new LoveDemo();
Love l = new Teacher(); //使用多态,将实现类中的对象传递到接口类中
ld.method(l);
}
}
————————————————————————————————————————————————————
引用类型作为返回值类型
返回值类型:
----| 基本类型:
----|引用类型:
----------| 类名作为返回值类型 :真正返回的是该类的对象。
----------| 抽象类作为返回值类型 :返回的是该抽象类的子类对象。
----------| 接口作为返回值类型 : 返回的是该接口的实现类的对象。
范例01:(类名作为返回值类型)
/*
一个方法的返回值类型是类名
那么真正返回的是该类的对象。
*/
class Student
{
public void study()
{
System.out.println("Good Good Study, Day Day Up");
}
}
class StudentDemo
{
public Student getStudent()
{
return new Student(); //返回一个匿名对象。等同于: Student s = new Student(); return s;
}
}
class ClassDemo_02
{
public static void main(String[] args)
{
//需求:要使用Student类中的study()方法。但不能直接创建Student对象,要使用StudentDemo帮助创建对象
StudentDemo sd =new StudentDemo();
//下面这个Student s 表示的是StudentDemo类中方法的Student返回值类型接收。
Student s = sd.getStudent(); //StudentDemo类中的Student类型接收 getStudent()方法中的返回值。
s.study();
}
}
范例02:(抽象类作为返回值类型)
/*
抽象类作为返回值类型
实际返回的是抽象类的子类对象。
*/
abstract class Person
{
public abstract void study();
}
class PersonDemo
{
public Person getPerson()
{
Person p = new Student(); //Person返回值类型的P 接收一个Student对象
return p; //返回Person类型的 p 值。
}
}
class Student extends Person
{
public void study() //重写抽象类Person中的抽象方法
{
System.out.println("Good Good Study, Day Day Up");
}
}
class AbstractDemo_02
{
public static void main(String[] args)
{
//需求:要测试Person类中的study()方法
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //Person返回值类型P 接收 getPerson方法传回来的值。
p.study();
}
}
范例03:(接口作为返回值类型)
/*
接口作为返回值类型
返回的是该接口的实现类的对象。
*/
interface Love
{
public abstract void love();
}
class LoveDemo
{
public Love getLove()
{
Love l = new Teacher(); //Teacher实现了Love接口,所以创建Teacher对象
return l;
}
}
class Teacher implements Love
{
public void love()
{
System.out.println("老师爱学生和java");
}
}
class InterfaceDemo_02
{
public static void main(String[] args)
{
//如何测试:
LoveDemo ld = new LoveDemo();
Love l = ld.getLove();
l.love();
}
}
————————————————————————————
链式编程
对象 . 方法().方法()
每次调用方法完毕后,返回的是一个对象。