郑州做网站多少钱,信息科技公司网站,洛阳网站建设的公司哪家好,哪些外贸网站比较好#x1f970;#x1f970;#x1f970;来都来了#xff0c;不妨点个关注叭#xff01; #x1f449;博客主页#xff1a;欢迎各位大佬!#x1f448; 文章目录 1. 多态1.1 多态是什么1.2 多态的意义1.3 多态的实现条件 2. 重写2.1 重写的概念2.2 重写的规则2.3 重写与重… 来都来了不妨点个关注叭 博客主页欢迎各位大佬! 文章目录 1. 多态1.1 多态是什么1.2 多态的意义1.3 多态的实现条件 2. 重写2.1 重写的概念2.2 重写的规则2.3 重写与重载的区别2.4 重写的设计 3. 向上转型和向下转型3.1 向上转型3.2 向下转型3.3 instanceof关键字 4. 多态的优缺点4.1 多态的优点4.2 多态的缺点 1. 多态
面向对象三大特性封装、继承、多态 今天我们一起来看看多态这一特性~~~
1.1 多态是什么
在生活中如果遇到特别伤心的事情或者心情很沮丧可能就会哭泣但在不同人身上哭泣的形式不一样比如臣妾做不到小女孩哇哇大哭还有大耳朵图图抱着妈妈的腿哭泣等等。总之同一件事情发生在不同对象上表现的形式是不一样的~ 【多态】通俗来说多种形态即去完成某个行为当不同的对象去完成时会产生出不同的状态
1.2 多态的意义
【多态的意义】 在于提高代码的复用性和扩展性同时实现接口统一并十分灵活可以根据不同的输入参数或条件调用不同的子类方法实现不同的功能易于维护和修改本期内容结尾将重点提到
1.3 多态的实现条件
在Java中实现多态的条件如下(缺一不可) (1) 必须在继承下 (2) 子类必须要对父类中方法进行重写 (3) 通过父类的引用调用重写的方法(向上转型) 多态体现的方面当传递不同类对象时会调用对应类中的方法 【代码】
public class Animal {String name;String gender;int age;public Animal(String name,String gender, int age) {this.name name;this.gender gender;this.age age;}public void eat() {System.out.println(name吃饭);}
}public class Cat extends Animal{public Cat(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name吃);}
}public class Dog extends Animal{public Dog(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name吃骨头);}
}public class Bird extends Animal{public Bird(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name啄米);}
}public class Test {public static void eat(Animal a) {a.eat();}public static void main(String[] args) {Cat cat new Cat(柚子,雌,2);Dog dog new Dog(球球,雄,1);Bird bird new Bird(泡芙,雌,2);eat(cat);eat(dog);eat(bird);}
}【运行结果】 【解释说明】 在上述代码中Animal、Cat、Dog和Bird类是类的实现者写的Test类是类的调用者写的 当类的调用者在编写 eat 这个方法的时传进来的参数类型为 Animal父类在该方法内部并不知道当前的a 引用指向的是哪个类型哪个子类的实例即a这个引用调用 eat方法可能会有多种不同的表现(a引用的实例相关比如猫类实例调用、狗类实例调用等eat表现的形式不同)这种行为称为多态 【图示】 【Override】 Override是jdk的注解用于指示一个方法是重写了父类中的方法 这个注解只在编译时有效不会保留在生成的字节码文件中 使用 Override 注解的优点 1提高代码的可读性和安全性 2在编译时检查可能的错误 但它不是必需要写的只要正确地重写了父类中的方法不使用 Override 注解代码仍能够正常运行 即使用或不使用取决于编码风格和习惯
2. 重写
2.1 重写的概念
【重写】也称为覆盖重写是子类对父类实现过程进行重新编写 返回值和形参都不能改变即外壳不变核心重写重写的好处是子类可以根据需要定义特定于自己的行为即子类能够根据需要实现父类的方法
2.2 重写的规则
【重写规则】 1子类在重写父类的方法时一般必须与父类的返回值类型 方法名 (参数列表) 完全一致 2被重写的方法返回值类型可以不同但必须具有父子类关系 3访问权限不能比父类中被重写的方法的访问权限更低(如父类方法被public修饰则子类中重写该方法不能声明为 private) 4父类被static、private、final修饰的方法、构造方法都不能被重写 5重写的方法可使用 Override 注解来显式指定能进行一些合法性校验检查可能会出现的错误(如不小心将方法名字写错 此时编译器就会发现父类中没有该方法则编译报错提示无法构成重写
2.3 重写与重载的区别 2.4 重写的设计
【重写的设计原则】对于已经投入使用的类尽量不要进行修改最好是重新定义一个新的类重复利用其中共性的内容并添加或者改动新的内容 举一个栗子吧~ 例如之前的电视机只能看正在播放的频道而当今时代科技越来越发达技术在进步现在的电视不仅可以看正在播放的频道还可以回看直播等等而我们不应该直接在原来的类修改因为原来的类可能仍有用户正在使用而正确的解决方式为新建一个新型电视机的类对可以看的内容这个方法进行重写增添更多的功能即达到需求 【静态绑定】即在编译时根据用户所传递实参类型就确定具体调用哪个方法代表函数重载 【动态绑定】即在编译时不能确定方法的行为需要等到程序运行时才能够确定具体调用哪个类的方法(发生多态的基础)
3. 向上转型和向下转型
3.1 向上转型
【向上转型】实际上是创建一个子类对象当父类对象使用 【语法格式】父类类型 对象名 new 子类类型(); 【语法举例】 Animal animal new Bird(“泡芙”,“雌”,2); animal是父类Animal类型即小的范围变成大的范围(是可以的)比如猫、狗和鸟等都是动物将子类对象转化为父类引用是合理、安全的大的范围包含小的范围
【使用场景】 1直接赋值 2方法传参 3方法返回 【具体使用代码举例如下】
public class Test1 {public static void main(String[] args) {Cat cat new Cat(柚子,雌,2);Dog dog new Dog(球球,雄,1);//1.直接复制 子类对象赋值给父类对象Animal bird new Bird(泡芙,雌,2);eat(cat);eat(dog);eat(bird);}//2.方法传参 形参的类型为Animal父类,可接受任意子类对象,即animal1的类型可以是猫、狗、鸟等子类public static void eat(Animal animal1) {animal1.eat();}//3.方法返回 返回任意子类对象public static Animal guessAnimal(String name) {if(球球.equals(name)) {return new Dog(球球,雄,1);}return null;}
}【优点】 让代码实现更简单灵活 【缺点】 不能调用到子类特有的方法只能调用父类的方法
3.2 向下转型
【向下转型】子类对象向上转型后当父类对象方法使用再无法调用子类的方法如需调用子类特有的方法将父类引用再还原为子类对象即可即向下转型在Java中向下转型是从一个更通用的类型向一个更具体的类型转换的过程 【语法格式】子类对象名 (子类类型) 对象名 【语法举例】 bird (Bird)animal; 【使用场景】 将它们转回具体的类型以利用它们的具体实现的情况
public class Animal {String name;String gender;int age;public Animal(String name,String gender, int age) {this.name name;this.gender gender;this.age age;}public void eat() {System.out.println(name吃饭);}
}public class Cat extends Animal{public Cat(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name吃);}public void meow() {System.out.println(猫在叫~);}
}public class Dog extends Animal{public Dog(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name吃骨头);}public void bark() {System.out.println(狗在叫~);}
}public class Bird extends Animal{public Bird(String name,String gender,int age) {super(name, gender, age);}Overridepublic void eat() {System.out.println(name啄米);}public void chirp() {System.out.println(小鸟叫~);}}public class Test2 {public static void main(String[] args) {Cat cat new Cat(柚子,雌,2);Dog dog new Dog(球球,雄,1);Bird bird new Bird(泡芙,雌,2);//向上转型Animal animal cat;animal.eat();animal dog;animal.eat();animal bird;animal.eat();//向下转型//程序可以通过编程但是会抛出异常,animal实际指向的是鸟,但现在强制还原为猫,无法还原//cat (Cat)animal;//cat.meow();//animal指向的是鸟,将animal还原为鸟是安全的bird (Bird)animal;bird.chirp();//instanceof 判断它左边的对象是否是它右边的类的实例,返回boolean的数据类型,是返回true否则返回false;if(animal instanceof Cat) {cat (Cat)animal;cat.meow();}if(animal instanceof Dog) {dog (Dog)animal;dog.bark();}//animal指向的是鸟,左边的对象animal是右边鸟类的实例,为true,执行if内容语句if(animal instanceof Bird) {bird (Bird) animal;bird.chirp();}}
}【运行结果】 【解释说明】
【优点】 可访问更具体类型的特定方法和属性明确正在处理的具体类型 【缺点】 不安全万一转换失败运行时会抛异常Java中为了提高向下转型的安全性引入instanceof关键字 如该表达式为true则可以安全转换较为麻烦
3.3 instanceof关键字
【概念】instanceof是Java中的保留关键字 【作用】测试它的左边对象是否是它的右边类的实例返回类型boolean类型 【用法】res 对象名 instanceof 类名; 【举例】以上述代码举例
4. 多态的优缺点
4.1 多态的优点
1能够避免使用大量的 if - else 如果需要打印多个形状不基于多态写则会有好几个if语句
public class Shape {public void draw() {System.out.println(画图形~);}
}public class Rectangle extends Shape{Overridepublic void draw() {System.out.println(◇);}
}public class Cycle extends Shape{Overridepublic void draw() {System.out.println(○);}
}
public class Fish extends Shape{Overridepublic void draw() {System.out.println();}
}public class Test3 {public static void drawShapes() {Rectangle rectangle new Rectangle();Cycle cycle new Cycle();Fish fish new Fish();String[] shapes {cycle,rectangle,fish};for(String x : shapes) {if(x.equals(cycle)) {cycle.draw();}else if(x.equals(rectangle)) {rectangle.draw();}else if(x.equals(fish)) {fish.draw();}}}public static void main(String[] args) {drawShapes();}
}基于多态编写代码创建一个Shape对象的数组则简洁明了~
public class Test3 {public static void drawShapes1() {Shape[] shapes {new Cycle(),new Rectangle(),new Fish()};for(Shape x: shapes) {x.draw();}}public static void main(String[] args) {drawShapes1();}
}两者打印结果一致所以可以避免大量的if-else语句 2可扩展能力更强 如果要新增加一种新的形状使用多态方式编写的代码改动成本较低体现可扩展性强比如我们要增加三角形这个形状类型
public class Triangle extends Shape{Overridepublic void draw() {System.out.println(△);}
}【解释说明】基于多态代码对类的使用者来说drawShapes方法只需创建一个新类的实例改动成本较低对于不基于多态的代码, 则需把drawShapes方法中的 if - else 进行修改改动成本更高
4.2 多态的缺点
代码的运行效率降低 1属性没有多态性当父类和子类都有同名属性时通过父类引用只能引用父类自己的成员属性 2构造方法没有多态性 A为父类在A类构造方法中调用func()方法B为子类B类中重写func()方法 【代码举例】
public class A {public A() {func();}public void func() {System.out.println(A.func());}
}public class B extends A{private String str ~;Overridepublic void func() {System.out.println(B.func() str);}
}public class Test4 {public static void main(String[] args) {B b new B();}
}
【运行结果】 【解释说明】 构造B对象的同时会调用A的构造方法 A的构造方法中调用func()方法此时会触发动态绑定即在编译时不能确定方法的行为等程序运行时确定是具体调用B类中的 func()方法此时B对象自身还没有构造, str是未初始化的状态为null如果具备多态性str的值应该是~即构造方法没有多态性 【结论】在构造函数内尽量避免使用实例方法除final和private方法 即尽量不要在构造器中调用方法如果这个方法被子类重写就会触发动态绑定但此时子类对象还没构造完成可能会出现一些隐藏但很难发现的问题带来不必要的麻烦 本期内容回顾 ✨✨✨本期内容到此结束啦~下期再见