Java语言基础(7)面向对象 您所在的位置:网站首页 java实现接口的类不能是抽象类 Java语言基础(7)面向对象

Java语言基础(7)面向对象

2024-07-10 06:16| 来源: 网络整理| 查看: 265

面向对象 3.1、 抽象类3.1.1、采用abstract声明抽象类3.1.2、抽象的方法只需在抽象类中,提供声明,不需要实现,起到了一个强制的约束作用,要求子类必须实现3.1.3、如果这个类是抽象的,那么这个类被子类继承,抽象方法必须被覆盖。如果在子类中不覆盖该抽象方法,那么必须将此方法再次声明为抽象方法3.1.4、抽象类不能被final修饰3.1.5、抽象方法不能被final修饰3.1.6、抽象类中可以没有抽象方法(参见3.1.1) 4.1、 接口(行为)4.1.1、接口中的方法默认都是public abstract的,不能更改4.1.2、接口中的变量是public static final类型的,不能更改,所以必须显示的初始化4.1.3、接口不能被实例化,接口中没有构造函数的概念4.1.4、接口之间可以[多]继承,但接口之间不能实现4.1.5、如果一个类实现了接口,那么接口中所有的方法必须实现4.1.6、一类可以实现多个接口4.1.7、一个接口可以继承多个接口4.1.8、 接口的进一步应用 接口和抽象类的区别?

3.1、 抽象类

看我们以前示例中的Person、Student和Employee,从我们使用的角度来看主要对Student和Employee进行实例化,Person中主要包含了一些公共的属性和方法,而Person我们通常不会实例化,所以我们可以把它定义成抽象的: ● 在java中采用abstract关键字定义的类就是抽象类,采用abstract关键字定义的方法就是抽象方法 ● 抽象的方法只需在抽象类中,提供声明,不需要实现 ● 如果一个类中含有抽象方法,那么这个类必须定义成抽象类 ● 如果这个类是抽象的,那么这个类被子类继承,抽象方法必须被重写。如果在子类中不复写该抽象方法,那么必须将此类再次声明为抽象类 ● 抽象的类是不能实例化的,就像现实世界中人其实是抽象的,张三、李四才是具体的 ● 抽象类不能被final修饰(它是需要被继承的) ● 抽象方法不能被final修饰,因为抽象方法就是被子类实现的 抽象类中可以包含方法实现,可以将一些公共的代码放到抽象类中,另外在抽象类中可以定义一些抽象的方法,这样就会存在一个约束,而子类必须实现我们定义的方法,如:teacher必须实现printInfo方法,Student也必须实现printInfo方法,方法名称不能修改,必须为printInfo,这样就能实现多态的机制,有了多态的机制,我们在运行期就可以动态的调用子类的方法。所以在运行期可以灵活的互换实现。 在这里插入图片描述

3.1.1、采用abstract声明抽象类 public class AbstractTest01 { public static void main(String[] args) { //不能实例化抽象类 //抽象类是不存在,抽象类必须有子类继承 Person p = new Person(); //以下使用是正确的,因为我们new的是具体类 Person p1 = new Employee(); p1.setName("张三"); System.out.println(p1.getName()); } } //采用abstract定义抽象类 //在抽象类中可以定义一些子类公共的方法或属性 //这样子类就可以直接继承下来使用了,而不需要每个 //子类重复定义 abstract class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } //此方法各个子类都可以使用 public void commonMethod1() { System.out.println("---------commonMethod1-------"); } } class Employee extends Person { } class Student extends Person { } 3.1.2、抽象的方法只需在抽象类中,提供声明,不需要实现,起到了一个强制的约束作用,要求子类必须实现 public class AbstractTest02 { public static void main(String[] args) { //Person p = new Employee(); //Person p = new Student(); //Person p = new Person(); p.setName("张三"); p.printInfo(); } } abstract class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } //此方法各个子类都可以使用 public void commonMethod1() { System.out.println("---------commonMethod1-------"); } //public void printInfo() { // System.out.println("------Person.printInfo()--------"); //} //采用abstract定义抽象方法 //如果有一个方法为抽象的,那么此类必须为抽象的 //如果一个类是抽象的,并不要求具有抽象的方法 public abstract void printInfo(); } class Employee extends Person { //必须实现抽象的方法 public void printInfo() { System.out.println("Employee.printInfo()"); } } class Student extends Person { //必须实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } 3.1.3、如果这个类是抽象的,那么这个类被子类继承,抽象方法必须被覆盖。如果在子类中不覆盖该抽象方法,那么必须将此方法再次声明为抽象方法 public class AbstractTest03 { public static void main(String[] args) { //此时不能再new Employee了 Person p = new Employee(); } } abstract class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } //此方法各个子类都可以使用 public void commonMethod1() { System.out.println("---------commonMethod1-------"); } //采用abstract定义抽象方法 public abstract void printInfo(); } abstract class Employee extends Person { //再次声明该方法为抽象的 public abstract void printInfo(); } class Student extends Person { //实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } 3.1.4、抽象类不能被final修饰 public class AbstractTest04 { public static void main(String[] args) { } } //不能采用final修改抽象类 //两个关键字是矛盾的 final abstract class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } //此方法各个子类都可以使用 public void commonMethod1() { System.out.println("---------commonMethod1-------"); } //采用abstract定义抽象方法 public abstract void printInfo(); } class Employee extends Person { //实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } class Student extends Person { //实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } 3.1.5、抽象方法不能被final修饰 public class AbstractTest05 { public static void main(String[] args) { } } abstract class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } //此方法各个子类都可以使用 public void commonMethod1() { System.out.println("---------commonMethod1-------"); } //不能采用final修饰抽象的方法 //这两个关键字存在矛盾 public final abstract void printInfo(); } class Employee extends Person { //实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } class Student extends Person { //实现抽象的方法 public void printInfo() { System.out.println("Student.printInfo()"); } } 3.1.6、抽象类中可以没有抽象方法(参见3.1.1) 4.1、 接口(行为)

接口我们可以看作是抽象类的一种特殊情况,在接口中只能定义抽象的方法和常量

在java中接口采用interface声明接口中的方法默认都是public abstract的,不能更改接口中的变量默认都是public static final类型的,不能更改,所以必须显示的初始化接口不能被实例化,接口中没有构造函数的概念接口之间可以继承,但接口之间不能实现接口中的方法只能通过类来实现,通过implements关键字如果一个类实现了接口,那么接口中所有的方法必须实现一类可以实现多个接口接口可以继承多个接口 4.1.1、接口中的方法默认都是public abstract的,不能更改 public class InterfaceTest01 { public static void main(String[] args) { } } //采用interface定义接口 //定义功能,没有实现 //实现委托给类实现 interface StudentManager { //正确,默认public abstract 等同public abstract void addStudent(int id, String name); public void addStudent(int id, String name); //正确 //public abstract void addStudent(int id, String name); //正确,可以加入public修饰符,此种写法较多 public void delStudent(int id); //正确,可以加入abstract,这种写法比较少 public abstract void modifyStudent(int id, String name); //编译错误,因为接口就是让其他人实现 //采用private就和接口原本的定义产生矛盾了 private String findStudentById(int id); } 4.1.2、接口中的变量是public static final类型的,不能更改,所以必须显示的初始化 public class InterfaceTest02 { public static void main(String[] args) { //不能修改,因为final的 //StudentManager.YES = "abc"; System.out.println(StudentManager.YES); } } interface StudentManager { //正确,默认加入public static final String YES = "yes"; //正确, 开发中一般就按照下面的方式进行声明 public static final String NO = "no"; //错误,必须赋值,因为是final的 //int ON; //错误,不能采用private声明 private static final int OFF = -1; } 4.1.3、接口不能被实例化,接口中没有构造函数的概念 public class InterfaceTest03 { public static void main(String[] args) { //接口是抽象类的一种特例,只能定义方法和变量,没有实现 //所以不能实例化 StudentManager studentManager = new StudentManager(); } } interface StudentManager { public void addStudent(int id, String name); } 4.1.4、接口之间可以[多]继承,但接口之间不能实现 public class InterfaceTest04 { public static void main(String[] args) { } } interface inter1 { public void method1(); public void method2(); } interface inter2 { public void method3(); } //接口可以继承 interface inter3 extends inter1 { public void method4(); } //接口不能实现接口 //接口只能被类实现 interface inter4 implements inter2 { public void method3(); } 4.1.5、如果一个类实现了接口,那么接口中所有的方法必须实现 public class InterfaceTest05 { public static void main(String[] args) { //Iter1Impl实现了Inter1接口 //所以它是Inter1类型的产品 //所以可以赋值 Inter1 iter1 = new Iter1Impl(); iter1.method1(); //Iter1Impl123实现了Inter1接口 //所以它是Inter1类型的产品 //所以可以赋值 iter1 = new Iter1Impl123(); iter1.method1(); //可以直接采用Iter1Impl来声明类型 //这种方式存在问题 //不利于互换,因为面向具体编程了 Iter1Impl iter1Impl = new Iter1Impl(); iter1Impl.method1(); //不能直接赋值给iter1Impl //因为Iter1Impl123不是Iter1Impl类型 //iter1Impl = new Iter1Impl123(); //iter1Impl.method1(); } } //接口中的方法必须全部实现 class Iter1Impl implements Inter1 { public void method1() { System.out.println("method1"); } public void method2() { System.out.println("method2"); } public void method3() { System.out.println("method3"); } } class Iter1Impl123 implements Inter1 { public void method1() { System.out.println("method1_123"); } public void method2() { System.out.println("method2_123"); } public void method3() { System.out.println("method3_123"); } } abstract class Iter1Impl456 implements Inter1 { public void method1() { System.out.println("method1_123"); } public void method2() { System.out.println("method2_123"); } //再次声明成抽象方法 public abstract void method3(); } //定义接口 interface Inter1 { public void method1(); public void method2(); public void method3(); } 4.1.6、一类可以实现多个接口

public class InterfaceTest06 {

public static void main(String[] args) { //可以采用Inter1定义 Inter1 inter1 = new InterImpl(); inter1.method1(); //可以采用Inter2定义 Inter2 inter2 = new InterImpl(); inter2.method2(); //可以采用Inter3定义 Inter3 inter3 = new InterImpl(); inter3.method3(); }

}

//实现多个接口,采用逗号隔开 //这样这个类就拥有了多种类型 //等同于现实中的多继承 //所以采用java中的接口可以实现多继承 //把接口粒度划分细了,主要使功能定义的含义更明确 //可以采用一个大的接口定义所有功能,替代多个小的接口, //但这样定义功能不明确,粒度太粗了 class InterImpl implements Inter1, Inter2, Inter3 {

public void method1() { System.out.println("----method1-------"); } public void method2() { System.out.println("----method2-------"); } public void method3() { System.out.println("----method3-------"); }

}

interface Inter1 {

public void method1();

}

interface Inter2 {

public void method2();

}

interface Inter3 {

public void method3();

}

/* interface Inter {

public void method1(); public void method2(); public void method3();

} */

4.1.7、一个接口可以继承多个接口 //声明接口:interface interface A{ public static final int CONST = 1; void a();//接口中的方法默认都是public abstract的 } interface K{ void k(); } //接口可以继承多个接口 interface B extends A,K{ void b(); int d(); } 4.1.8、 接口的进一步应用

在java中接口其实描述了类需要做的事情,类要遵循接口的定义来做事,使用接口到底有什么本质的好处?可以归纳为两点:(提供了标准、规范) ● 采用接口明确的声明了它所能提供的服务 ● 解决了Java单继承的问题(一个类可以实现多个接口,一个接口可以继承多个接口) ● 实现了可接插性(重要) 示例:完成学生信息的增删改操作,系统要求适用于多个数据库,如:适用于Oracle和MySQL; 第一种方案,不使用接口,每个数据库实现一个类: 在这里插入图片描述

//Oracle的实现 public class StudentOracleImpl { public void add(int id, String name) { System.out.println("StudentOracleImpl.add()"); } public void del(int id) { System.out.println("StudentOracleImpl.del()"); } public void modify(int id, String name) { System.out.println("StudentOracleImpl.modify()"); } }

需求发生变化了,客户需要将数据移植Mysql上

Mysql的实现 public class StudentMysqlImpl { public void addStudent(int id, String name) { System.out.println("StudentMysqlImpl.addStudent()"); } public void deleteStudent(int id) { System.out.println("StudentMysqlImpl.deleteStudent()"); } public void udpateStudent(int id, String name) { System.out.println("StudentMysqlImpl.udpateStudent()"); } }

调用以上两个类完成向Oracle数据库和Mysql数据存储数据

public class StudentManager { public static void main(String[] args) { //对Oracle数据库的支持 /* StudentOracleImpl studentOracleImpl = new StudentOracleImpl(); studentOracleImpl.add(1, "张三"); studentOracleImpl.del(1); studentOracleImpl.modify(1, "张三"); */ //需要支持Mysql数据库 StudentMysqlImpl studentMysqlImpl = new StudentMysqlImpl(); studentMysqlImpl.addStudent(1, "张三"); studentMysqlImpl.deleteStudent(1); studentMysqlImpl.udpateStudent(1, "张三"); } }

以上代码不能灵活的适应需求,当需求发生改变需要改动的代码量太大,这样可能会导致代码的冗余,另外可能会导致项目的失败,为什么会导致这个问题,在开发中没有考虑到程序的扩展性,就是一味的实现,这样做程序是不行的,所以大的项目比较追求程序扩展性,有了扩展性才可以更好的适应需求。

第二种方案,使用接口 UML,统一建模语言 在这里插入图片描述

public class Student4OracleImpl implements IStudent { public void add(int id, String name) { System.out.println("Student4OracleImpl.add()"); } public void del(int id) { System.out.println("Student4OracleImpl.del()"); } public void modify(int id, String name) { System.out.println("Student4OracleImpl.modify()"); } } public class Student4MysqlImpl implements IStudent { public void add(int id, String name) { System.out.println("Student4MysqlImpl.add()"); } public void del(int id) { System.out.println("Student4MysqlImpl.del()"); } public void modify(int id, String name) { System.out.println("Student4MysqlImpl.modify()"); } } public class StudentService { public static void main(String[] args) { /* IStudent istudent = new Student4OracleImpl(); IStudent istudent = new Student4MysqlImpl(); istudent.add(1, "张三"); istudent.del(1); istudent.modify(1, "张三"); */ //IStudent istudent = new Student4OracleImpl(); //IStudent istudent = new Student4MysqlImpl(); //doCrud(istudent); //doCrud(new Student4OracleImpl()); //doCrud(new Student4MysqlImpl()); //doCrud(new Student4OracleImpl()); doCrud(new Student4MysqlImpl()); } //此种写法没有依赖具体的实现 //而只依赖的抽象,就像你的手机电池一样:你的手机只依赖电池(电池是一个抽象的事物), //而不依赖某个厂家的电池(某个厂家的电池就是具体的事物了) //因为你依赖了抽象的事物,每个抽象的事物都有不同的实现 //这样你就可以利用多态的机制完成动态绑定,进行互换,是程序具有较高的灵活 //我们尽量遵循面向接口(抽象)编程,而不要面向实现编程 public static void doCrud(IStudent istudent) { istudent.add(1, "张三"); istudent.del(1); istudent.modify(1, "张三"); } //以下写法不具有扩展性 //因为它依赖了具体的实现 //建议不要采用此种方法,此种方案是面向实现编程,就依赖于具体的东西了 /* public static void doCrud(Student4OracleImpl istudent) { istudent.add(1, "张三"); istudent.del(1); istudent.modify(1, "张三"); } */ } 接口和抽象类的区别? 接口描述了方法的特征,不给出实现,一方面解决java的单继承问题,实现了强大的可接插性抽象类提供了部分实现,抽象类是不能实例化的,抽象类的存在主要是可以把公共的代码移植到抽象类中面向接口编程,而不要面向具体编程(面向抽象编程,而不要面向具体编程)优先选择接口(因为继承抽象类后,此类将无法再继承,所以会丧失此类的灵活性)


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有