当一个抽象类,如果抽象类中的所有方法都是抽象的,那么我们就可以把它定义为一个接口,接口是对行为的抽象。类是对属性和行为的抽象。
语法
public interface 接口名{
//接口成员
}
1.接口中的方法的定义不需要abstract来修饰,默认就是抽象的
2.接口是不可以实例化的,需要有类来实现接口
3.接口中的方法不能和private,static和final共存
4.在接口中可以定义”属性”,可以通过接口的实现类的实例来访问(不推荐),推荐使用接口名.常量,这是一个常量默认是public, static ,final
注意:常量的定义命名的规范要使用大写,单词之间要用“_”分隔。
5.接口可以继承接口(多继承)
接口中可以多继承,即接口可以继承接口
[修饰符] interface 接口名 extends 父接口1,父接口2,···{
常量定义
方法定义
}
实现接口的语法:
public class 类名 implements 接口名,接口名,…{
//实现每一个接口中的方法
}
使用接口方式计算圆和正方形的面积和周长。
interface Cal{
/**
定义圆周率
*/
public static final double PI = 3.14;
/**
求周长
*/
public double getLong();
/**
求面积
*/
public double getArea();
}
class Rect implements Cal{
//边长
double r;
public Rect(double r){
this.r = r;
}
public double getLong(){
return 4*r;
}
public double getArea(){
return r*r;
}
}
class Circle implements Cal{
//半径
double r;
public Circle(double r){
this.r = r;
}
public double getLong(){
return 2*Cal.PI *r;
}
public double getArea(){
return Cal.PI * r *r;
}
}
public class TestCal{
public static void main(String[] args){
//创建一个正方形
Rect rect = new Rect(10.0);
double rectLong = rect.getLong();
double rectArea = rect.getArea();
System.out.println("正方形的周长是:"+rectLong);
System.out.println("正方形的面积是:"+rectArea);
//创建一个圆
Circle c = new Circle(10.0);
double cLong = c.getLong();
double cArea = c.getArea();
System.out.println("圆的周长是:"+cLong);
System.out.println("圆的面积是:"+cArea);
}
//正方形的周长是:40.0
//正方形的面积是:100.0
//圆的周长是:62.800000000000004
//圆的面积是:314.0
}
interface ArrayUtils{//遍历数组的工具
public static void printArr(int[] arr){
for(int i = 0; i < arr.length; i++)
System.out.print(arr[i]+"\t");
}
}
public class TestUtils{
public static void main(String[] args){
ArrayUtils.printArr(new int[]{1,2,3,4,5});
}
//1 2 3 4 5
}
interface Person{
public default void learn(){
System.out.println("我是一个默认实现的方法");
}
}
class Student implements Person{
/*
public void learn(){
System.out.println("学生在学习数学");
}
*/
}
public class TestPerson{
public static void main(String[] args){
Student s = new Student();
s.learn();
}
}
//我是一个默认实现的方法
1.接口是行为的抽象可以有静态方法,抽象方法和默认方法,抽象类中可以有所有方法。
2.接口和抽象类都不能实例化,接口需要类来实现后实例化实现类,抽象类需要类来继承然后实例化子类。
3.抽象类只能单继承,接口可以多继承接口(jdk1.7),接口还可以多实现。
4.接口中的“属性”是public static final类型的,抽象类中的属性跟普通类中的属性没有区别。
5.接口中的方法默认就是抽象的不需要加absract,抽象类中的抽象方法需要加abstract关键字。
子类转换为父类(向上转型)
子类可以自动转型成父类
class Person{
String name;
public void eat(){
System.out.println(name+"在吃饭");
}
}
class Student extends Person{
public void eat(){
System.out.println(name+"在吃鱼");
}
}
public class TestPerson{
public static void main(String[] args){
//子类自动转换成父类
Person person = new Student();
person.name = "张三";
person.eat();//张三在吃鱼
}
}
如果子类对父类的方法有覆写,并且子类的实例赋值给父类的引用,通过这个引用来调用这个覆写的方法的时候,调用的是子类。
父类指向子类的实例的引用不能调用子类的特有的方法和属性。
如果父子类有同名的属性,那么父类指向子类的实例的引用调用这个属性的时候调用的还是父类的,不要和方法混淆。
父类转换为子类(向下转型)
特点:
父类转换成子类不能自动完成。
父类转换成子类的前提是父类的真身是这个子类,转回子类后,就可以访问子类内部的方法和属性。
如果这个父类的真身是子类B,不能强制转换成子类A,只能转换成B。
抽象类作为父类同样符合上述理论
接口中也是完全符合上述理论,但是注意接口中没有属性。
class Person{
String name;
public void eat(){
System.out.println(name+"在吃饭");
}
}
class Student extends Person{
public void eat(){
System.out.println(name+"在吃鱼");
}
public void learn(){
System.out.println(name+"在学习");
}
}
public class TestPerson{
public static void main(String[] args){
Person p = new Student();
p.name = "张三";
//强制转换
Student student = (Student) p;
student.eat();//张三在吃鱼
student.learn();//张三在学习
}
}
同一个事件发生在不同的对象上会产生不同的结果。
多态就是行为具有表现多种功能的能力。
在程序设计的术语中,它意味着一个特定类型的变量可以引用不同类型的对象,并且能自动的调用引用的对象的方法,也就是根据作用到不同对象类型,响应不同的操作。
多态存在的三个必要条件:继承,重写,父类引用指向子类对象
可替换性:多态对已存在的代码具有可替换性。
可扩充性:多态对代码具有扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。
接口性:多态是父类向子类提供了一个共同接口,由子类来具体实现。
灵活性:多态的应用中体现了灵活多样的操作,提高了使用效率。
简化性:多态简化了应用软件的代码编程和修改过程。
interface Person{
public void eat();
}
class Student implements Person{
String name;
public void eat(){
System.out.println(name+"在吃饭");
}
public void learn(){
System.out.println(name+"在学习");
}
}
public class TestPerson{
public static void main(String[] args){
Student s = new Student();
s.name = "张三";
Person p = s;
p.eat();
Student student = (Student) p;
student.learn();
//张三在吃饭
//张三在学习
}
}
使用父类作为方法的形参
实例:假如狗、猫、鸭3种动物被一个主人领养,主人可以控制各种动物叫的行为,实现一个主人类,在该类中定义控制动物叫的方法。
//主人类
class Host{
//让动物叫的方法
public void letCry(Animal animal){
animal.cry();
}
}
class Animal{
public void cry(){
System.out.println("叫");
}
}
class Dog extends Animal{
public void cry(){
System.out.println("狗叫");
}
}
class Cat extends Animal{
public void cry(){
System.out.println("猫叫");
}
}
class Duck extends Animal{
public void cry(){
System.out.println("鸭叫");
}
}
public class Test {
public static void main(String[] args) {
Host host = new Host();
Animal animal;
animal = new Dog();
host.letCry(animal);//控制狗叫
animal = new Cat();
host.letCry(animal);//控制猫叫
animal = new Duck();
host.letCry(animal);//控制鸭叫
//狗叫
//猫叫
//鸭叫
}
}
使用父类作为方法的返回值
//动物类
class Animal{
public void cry(){
System.out.println("叫");
}
}
class Dog extends Animal{
public void cry(){
System.out.println("狗叫");
}
}
class Cat extends Animal{
public void cry(){
System.out.println("猫叫");
}
}
class Duck extends Animal{
public void cry(){
System.out.println("鸭叫");
}
}
//主人类
class Host{
//让动物叫的方法
public Animal letCry(String type){
Animal animal = new Animal();
if (type=="dog"){
animal = new Dog();
}else if (type=="cat"){
animal = new Cat();
}else if (type=="duck"){
animal = new Duck();
}
return animal;
}
}
public class Test {
public static void main(String[] args) {
Host host = new Host();
Animal animal;
animal = host.letCry("dog");
animal.cry();//狗叫
animal = host.letCry("cat");
animal.cry();//猫叫
animal = host.letCry("duck");
animal.cry(); //鸭叫
}
}
x instanceof A:检验x是否为类A的对象,返回值为boolean类型
public class Test01 {
public static void main(String[] args) {
Test01 t = new Test01();
System.out.println(t instanceof Object);//true
}
}
摘取代码中变化的行为,形成接口
多用组合,少用继承
针对接口编程,不依赖于具体实现
针对扩展开放,针对改变关闭