Java阶段二: 面向对象的多态特性及抽象类和接口

您所在的位置:网站首页 面向对象的多态的特性及意义 Java阶段二: 面向对象的多态特性及抽象类和接口

Java阶段二: 面向对象的多态特性及抽象类和接口

2024-07-15 07:07| 来源: 网络整理| 查看: 265

(1)多态 (2)抽象类 (3)接口 (4)内部类

1.多态(重中之重)

1.1 基本概念 多态主要指同一种事物表现出来的多种形态。 饮料:可乐、雪碧、脉动、乐虎、红牛、… 宠物:狗、猫、鸟、乌龟、鱼、… 人:学生、教师、工人、…

1.2 语法格式 父类类型 引用变量名 = new 子类类型(); 如: Person pw = new Worker(); pw.show();

解析: 编译阶段调用Person类中show方法,在运行阶段调用Worker类中重写以后的show方法

练习: 编程实现Person类的封装,特征有:姓名和年龄,要求提供打印所有特征的行为。 编程实现Worker类的封装继承Person类,特征有:薪水。

Person类:

package Test; //定义Person类 public class Person { private String name; private int age; public Person(){} public Person(String name,int age){ setName(name); setAge(age); } public void setName(String name){ this.name=name; } public void setAge(int age){ this.age=age; } public String getName(){ return name; } public int getAge(){ return age; } public void show(){ System.out.println("姓名:"+getName()+" "+"年龄:"+getAge()); } public static void test(){ System.out.println("父类中的静态方法!!!"); } }

Worker类:

package Test; public class Worker extends Person{ private int salary; public Worker(){} public Worker(String name,int age,int salary){ super(name,age); setSalary(salary); } public void setSalary(int salary){ if (salary>2021) { this.salary = salary; }else{ System.out.println("大兄弟你可省点心吧!!!,你这工资都低于最低工资了"); } } public int getSalary(){ return salary; } @Override public void show(){ super.show(); System.out.println("工资:"+getSalary()); } public static void test(){ System.out.println("子类的静态方法!!!"); } }

PersonWorkerTest类:

package Test; public class PersonWorkTest { public static void main(String[] args) { //1:声明父类类型的引用指向父类类型的对象,没有多态 Person p=new Person("关羽",30); //声明子类没有重写show方法时,下面调用的父类show方法 //当子类重写show方法后,下面调用的是父类的show方法 p.show(); System.out.println("-------------------"); //2:声明子类类型的引用指向子类类型的对象,没有多态 Worker w=new Worker("张飞",28,40000); //当子类没有重写show方法时,下面调用的是父类的show方法 //当子类重写show方法后,下面调用的是子类的show方法 w.show(); System.out.println("-------------------"); //3:声明父类类型的引用指向子类类型的对象,形成了多态 //子类 is a父类 //实现从Worker类型到Person类型的转换,从小到大的转换,自动类型转换 Person pw =new Worker("李白",22,8000); //当子类没有重写show方法时, 下面调用父类的show方法 //当子类重写show方法后,下面调用子类的show方法 //在编译阶段调用父类的show方法, 在运行阶段调用子类重写的版本 pw.show(); System.out.println("-----------------------"); //4:测试一下父类的引用是否能够调用父类独有的方法以及子类独有的方法 String str1=pw.getName(); System.out.println("获取到的姓名是:"+str1); // pw.salary(); System.out.println("-----------------------"); pw.test(); Person.test(); System.out.println("-----------------------"); //5:若希望父类引用可以调用子类独有的方法,则需要强制类型转换 //从Person类型向Worker类型的转换,大到小的转换,强制类型转换 int num =((Worker) pw).getSalary(); System.out.println("获取到的薪水是:"+num);//8000 //从person类型向String类型的转换编译报错,因此到不了运行阶段 //String str2=(String)pw; //从Person类型向Teacher类型的转换编译通过 //运行发生ClassCastException类型转换异常 //Worker类型不能转换到Teacher类型 //Teacher t=(Teacher)pw; if (pw instanceof Teacher){ System.out.println("可以放心的转换了!"); }else{ System.out.println("转换有风险,操作需谨慎!!!"); } } }

运行结果: 在这里插入图片描述

1.3 多态的效果 (1)当父类的引用指向子类的对象时,父类的引用可以直接调用父类独有的方法; (2)当父类的引用指向子类的对象时,父类的引用不可以直接调用子类独有的方法; (3)对于父子类都有的非静态成员方法来说,编译阶段调用父类版本,运行阶段 调用子类重写以后的版本; (4)对于父子类都有的静态方法来说,编译和运行阶段调用父类版本,隶属于类层级, 因此与指向的对象无关;】 1.4多态的使用场合 a:通过方法发参数传递形成多态 public static void draw(Shape s){} TestShape.draw(new Rect(1,2,3,4)) b:在方法体中直接使用多态的语法格式 TestAbstract ta=new SubTestAbstract(); ta.show();

2.抽象类(重点) 2.1 抽象方法的概念 抽象方法就是指不能具体实现的方法,也就是没有方法体并使用abstract关键字修饰 语法格式: 访问控制符 abstract 返回值类型 方法名称(形参列表); 如: public abstract void cry();

2.2 抽象类的概念 抽象类就是指不能具体实例化的类,也就是不能创建对象并使用abstract关键字修饰

2.3 注意事项 (1)抽象类中可以有成员变量、构造方法以及成员方法; (2)抽象类中可以有抽象方法也可以没有抽象方法; (3)拥有抽象方法的类必须是抽象类,因此严格来说,具有抽象方法并且使用 abstract关键字修饰的类才算真正意义上的抽象类。

2.4 实际意义 抽象类的意义不在于自身创建对象而在于被继承,当一个类继承抽象类后必须重写抽象类中的抽象方法,否则该类也变成抽象类。 也就是说抽象类对子类具有强制性和规范性,因此叫做模板设计模式。

经验分享: 在以后的开发中推荐使用多态的语法格式,当父类的引用指向子类的对象时,那么父类引用直接调用的所有方法一定是父类拥有的方法,若希望更换子类时,只需要将new关键字后面的类型修改而其它地方无需更改立即生效,从而提高了代码的可维护性。 该方式的缺点就是:父类引用不能直接访问子类独有的方法,若访问则需要强转。

3.接口(重点) 3.1 基本概念 接口就是一种比抽象类还抽象的类,体现为所有成员方法都是抽象方法。 定义类的关键字是class,而定义接口的关键字是interface。 继承类的关键字是extends,而实现接口的关键字是implements。

3.2 类和接口之间的关系 类和类之间的关系 使用extends关键字表达继承的关系 支持单继承 类和接口之间的关系 使用implemets关键字表达实现的关系 支持多实现 接口和接口之间的关系 使用extends关键字表达继承的关系 支持多继承

3.3 抽象类和接口之间的区别(笔试题) (1)定义抽象类的关键字是abstract class,而定义接口的关键字是interface。 (2)继承抽象类的关键字是extends,而实现接口的关键字是implements。 (3)继承抽象类支持单继承,而实现接口可以多实现。 (4)抽象类中可以有构造方法,而接口中不可以有构造方法。 (5)抽象类中可以有成员变量,而接口中只可以有常量。 (6)抽象类中可以有成员方法,而接口中只可以有抽象方法。 (7)抽象类中增加方法可以不影响子类,而接口中增加方法通常都影响子类。 (8)从jdk1.8开始允许接口中出现非抽象方法,但需要使用default关键字修饰。

接口的可以满足多继承,金属类,货币类,黄金类可以继承金属类和货币类,我是创建了一个second包,所以每一个类的开始都会有这一句话:package second;

货币类:

package second; //金属类,货币类,黄金类可以继承金属类和货币类 public interface Money { //自定义抽象方法描述买东西的行为 public abstract void buy(); }

金属类:

package second; public interface Metal { //自定义抽象方法来描述发光的行为 public abstract void shine(); //让接口中增加方法后不影响实现类 public default void test(){ System.out.println("增加这个方法是否重写可以取决于你的心情吧"); } }

黄金类:

package second; public class Gold implements Metal,Money { @Override public void shine(){ System.out.println("是金子总会发光!!!"); } @Override public void buy(){ System.out.println("买了自己喜欢的物品,开心吧!!!"); } public static void main(String[] args) { //接口类型的引用指向实现类的对象,形成了多态 Metal mt=new Gold(); mt.shine(); System.out.println("----------------"); Money nn=new Gold(); nn.buy(); } }

4.匿名内部类(重点、难点) 4.1 语法格式 接口/父类类型 引用变量名 = new 接口/父类类型(){ 方法的重写 };

4.2 经验的分享 当接口类型的引用作为方法的形参时,实参的传递方式有两种: a.自定义类实现接口,然后创建该类的对象作为实参传递; b.使用匿名内部类的语法格式来得到接口类型的引用作为实参传递;

5:内部类() 5.1基本概念: 当一个类的定义出现在另外一个类的类体中时,那么这个类就叫做内部类,而这个内部类所在的类叫外部类。 类中的内容:成员变量、成员方法、够早方法、静态成员,构造块和静态代码块、内部类 5.2语法格式: class 外部类类名{ class 内部类名{ 内部类的类体 } } 如: class A { class B{ } } 5.3:实际作用: 当一个类存在的价值仅仅是为了某一个类单独服务是,那么久可以将这个类定义所服务类中的内部类,这样可以隐藏该类的实现细节并且可以方便的访问呢外部类的私有成员不需要在提供公有的get和set方法。 5.4:基本分类: 1:普通内部类—直接将一个类的定义放在另一个类的类体中。

package FIFI; public class GenerICLass { private int cen=1; //在类体中定义一个普通内部类,隶属于对象层级 class Inner{ void show(){ System.out.println("cen="+cen); } } public static void main(String[] args) { //声明外部类的引用指向外部类的对象 GenerICLass it=new GenerICLass(); //声明内部类的引用指向内部类的对象后调用show方法 // inner in= new inner();声明报错 Inner in=it.new Inner(); in.show(); } }

2:静态内部类–使用static关键字修饰的内部类,隶属于类层级

package FIFI; public class innerTest { private int cent=1;//隶属于对象层级 private static int snt=2;//隶属于类层级 //自定义静态内部类,隶属于类层级 static class Inner{ //定义show方法 void show(){ // error 静态成员不能访问非静态成员变量 // System.out.println("cent="+cent); // 自己类的里面不需要类名.调用 System.out.println("snt="+snt); } public static void main(String[] args) { //声明静态内部类的引用指向静态内部类的对象 Inner in = new Inner(); //调用show方法 in.show(); } } }

局部内部类—直接将一个类的定义放在放方法体的内部时 —作用范围是从声明开始一直到方法体结束

package FIFI; public class TestAreaInner { public void show(){ //方法体中定义局部内部类 class Inner{ void test(){ System.out.println("局部内部类!!!"); } } Inner it=new Inner(); it.test(); } public static void main(String[] args) { TestAreaInner in=new TestAreaInner(); in.show(); } }

运行结果: 在这里插入图片描述 一个有意思的题目: 3.自定义InterfaceA接口,里面含有一个抽象方法int method(int n);

package FIFI; public interface InterfaceA { //自定义抽象方法 public abstract int method(int n); } 自定义ClassA类实现InterfaceA接口并重写method方法,要求计算1到n的和并返回 package FIFI; public class A implements InterfaceA{ @Override public int method(int n){ int a=0; for (int i=0;i 0;i--){ a*=i; } return a; } } 自定义TestInterface测试类,里面包含一个参数为InterfaceA接口形参的方法, 并在该方法体中调用method方法,最后在main方法中调用该方法。 package FIFI; public class TestInterface { //自定义成员方法让接口类型的引用作为方法的形参 public static void show(InterfaceA ia){ int res = ia.method(5); System.out.println("最终的就是结果是:"+res); } public static void main(String[] args) { //并在该方法体中调用method方法,最后在main方法中调用该方法。 TestInterface.show(new A()); System.out.println("------------------"); TestInterface.show(new B()); } }

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3