山西专业网站建设大全,上海网站建设排名公司,网站推荐正能量,怎么创建一个公司网站向上转型和向下转型
向上转型 定义#xff1a;实际就是创建一个子类对象#xff0c;将其当作父类对象来使用。 语法格式#xff1a;父类类型 对象名 new 子类类型() Animal animal new Cat(元宝#xff0c; 2); animal是父类类型#xff0c;但是可以引用子…向上转型和向下转型
向上转型 定义实际就是创建一个子类对象将其当作父类对象来使用。 语法格式父类类型 对象名 new 子类类型() Animal animal new Cat(元宝 2); animal是父类类型但是可以引用子类对象因为是从小范围到大范围的转换。 特点 编译时多态性 父类引用变量可以引用子类对象编译器会在编译时检查引用变量的类型是否与对象的类型兼容。 运行时多态性 在运行时根据引用变量所指向的实际对象类型来调用对应的方法实现方法的多态性。 限制方法访问 向上转型后只能调用父类中声明的方法而不能直接调用子类新增的方法。 使用场景1.直接赋值 2.方法传参 3.方法返回
举例一直接赋值
class Animal {void makeSound() {System.out.println(Animal makes a sound);}
}class Dog extends Animal {void makeSound() {System.out.println(Dog barks);}
}public class Main {public static void main(String[] args) {Animal animal new Dog(); // 直接赋值animal.makeSound(); // 调用的是 Dog 类的方法}
}
举例二方法传参
class Shape {void draw() {System.out.println(draw a shape);}
}class Circle extends Shape {Overridevoid draw() {System.out.println(draw a circle);}
}class Triangle extends Shape {Overridevoid draw() {System.out.println(draw a triangle);}
}
public class Test {public static void shapeDrawing(Shape s) {s.draw();}public static void main(String[] args) {Shape s1 new Circle();Shape s2 new Triangle();shapeDrawing(s1);shapeDrawing(s2);//方法传参传递不同子类对象}
}举例三做返回值
class Vehicle {String getType() {return Vehicle;}
}class Car extends Vehicle {OverrideString getType() {return Car;}
}class Bike extends Vehicle {OverrideString getType() {return Bike;}
}public class Test {public static Vehicle getType(String type){if(type.equals(car)){return new Car();} else if(type.equals(bike)) {return new Bike();} else {return new Vehicle();}}public static void main(String[] args) {Vehicle v1 getType(car);Vehicle v2 getType(bike);Vehicle v3 getType(plane);System.out.println(v1.getType());System.out.println(v2.getType());//方法返回返回的实际上可能是子类对象System.out.println(v3.getType());}
}向上转型的优点让代码实现更加简单灵活 向上转型的缺点不能调用到子类特有的方法 向下转型 将一个子类对象经过向上转型之后当作父类方法使用在无法调用子类的方法但有时候可能需要调用子类特有的方法此时将父类引用还原为子类对象即可即向下转换。 class Animal1 {void makeSound() {System.out.println(Animal makes a sound);}
}class Dog1 extends Animal1 {Overridevoid makeSound() {System.out.println(Dog barks);}void fetch() {System.out.println(Dog fetch the ball);}
}public class Test1 {public static void main(String[] args) {Animal1 animal1 new Dog1();//向上转型//向下转型if(animal1 instanceof Dog1) {Dog1 dog (Dog1)animal1;//实例类型检查和向下转型dog.makeSound();//调用子类的方法dog.fetch();//调用子类特有的方法}}
}向下转型用的比较少而且不安全万一转换失败运行时就会抛出异常。Java中为了提高向下转型的安全性引入了instanceof用于检查一个对象是否是指定类或其子类的实例如果表达式的结果为true则可以安全转换。 多态的优缺点
优点
假设有如下代码
class Shape {//属性。。。public void draw() {System.out.println(画图形);}
}class Rect extends Shape {Overridepublic void draw() {System.out.println(⎕);}
}class Circle extends Shape {Overridepublic void draw() {System.out.println(◉);}
}class Star extends Shape {Overridepublic void draw() {System.out.println(★);}
}1.能够降低代码的“圈复杂度”避免使用大量的if-else 圈复杂度一种描述一段代码复杂程度的方式。一段代码如果平铺直叙那么就比较简单容易理解而如果有很多条件分支或者循环语句就认为了解起来比较复杂。 因此我们可以简单粗暴的计算一段代码中条件语句和循环语句出现的个数这个个数就称为“圈复杂度”如果一个方法的圈复杂度太高就需要考虑重构 不同公司对于圈复杂度的规范不一样但一般不会超过10 例如我们现在需要的不只是打印一个形状了而是多个形状如果不基于多态实现代码如下
public static void drawShapes() {Rect rect new Rect();Circle circle new Circle();Star star new Star();String[] shapes {circle, rect, circle, rect, star};for(String shape : shapes) {if(shape.equals(circle)){circle.draw();} else if(shape.equals(rect)) {rect.draw();} else if(shape.equals(star)) {star.draw()}}}
如果使用多态则不必写这么多的if-else分支语句代码更简单。
Shape[] shapes {new Circle(), new Rect(), new Circle(), new Rect(), new Star()};
for(Shape shape : shapes) {shape.draw();
}
2.可扩展能力更强 如果要新增一种形状使用多态的方式代码改动成本也比较低。 class Triangle extends Shape {Override public void draw() {System.out.println(▲);}
} 对于类的调用者主函数只要创建一个新类的实例就可以了改动成本很低。 而对于不用多态的情况就要把drawShapes中的if-else进行一定修改改动成本更高 缺点
代码运行效率降低 1.属性没有多态性当父类和子类都有同名属性的时候通过父类引用只能引用父类自己的成员属性 2.构造方法没有多态性