一、面向对象的基本特征
- 1、封装 和权限修饰符有关
- 2、继承 extends
- 3、多态
- 多态:多种形式
- 变量的引用形式:
- (1)本态引用:左边的变量与右边的对象是同一种类型
- (2)多态引用:左边的对象时父类类型,右边的对象时子类的对象
- 多态表象出来的特征:
- 编译的时候是按照父类类型进行编译
- 执行的方法是子类重写的方法
- 前提:继承,重写,多态引用
- 用途:方法的动态绑定
public class TestPolymorphism {
public static void main(String[] args) {
//本态引用
//Person p = new Person();
//Woman w = new Woman();
//Man m = new Man();
//多态引用
Person p2 = new Woman();
Person p3 = new Man();
p2.eat();
p2.walk();
}
}
class Person{
public void eat(){
System.out.println("吃饭");
}
public void walk(){
System.out.println("走路");
}
}
class Woman extends Person{
public void eat(){
System.out.println("狼吞虎咽");
}
public void walk(){
System.out.println("走小路");
}
public void buy(){
System.out.println("买东西");
}
}
class Man extends Person{
public void eat(){
System.out.println("吃汉堡");
}
public void walk(){
System.out.println("走大路");
}
public void smoke(){
System.out.println("抽烟");
}
}
多态的好处:
- 使程序员编写代码更灵活
- 多态的应用:
-
(1)多态数组
-
数组的元素是父亲的类型,实际上存储的是子类的对象
-
用这样的数组可以统一管理所有子类的对象
public class TestUse {
public static void maim(String[] args){
/*
* 创建一个数组,可以存储各种图形对象,包括园对象,矩形对象。。。
*/
//本态数组
//Circle[] yuans=new Circle[3];
//Rectangle[] jus=new Rectangle[3];
Graphic[] all=new Graphic[3];
all[0]=new Circle(1.2);
all[1]=new Rectangle(2,4);
all[2]=new Circle(1.5);
//遍历所有图形的面积
for(int i=0;i<all.length;i++){
System.out.println(all[i].getArea());
}
}
}
class Graphic{
public double getArea(){
return 0.0;//无意义,保证格式正确
}
}
class Circle extends Graphic{
private double radius;
public Circle(double radius) {
super();
this.radius = radius;
}
public double getArea(){
return 3.14*radius*radius;
}
}
class Rectangle extends Graphic{
private double length;
private double width;
public Rectangle(double length, double width) {
super();
this.length = length;
this.width = width;
}
public double getArea(){
return length*width;
}
}
(2)多态参数:
-
行参是父亲类型,实参是子类对象
public class TestUse2 {
//这个方法检查所有的动物吃东西是否正常
//没有多态就需要重载很多个
/*
* public static void eat(Dog dog){
* dog.eat();
* }
*/
public static void check(Animal a){
a.eat();
}
public static void main(String[] args) {
check(new Dog());//隐含了,形参Animal a = 实参 new Dog()
check(new Cat());
Dog d = new Dog();
check(d);
}
}
class Animal{
public void eat(){
System.out.println("吃东西");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("啃骨头");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("吃鱼");
}
}
练习1
1、 声明Traffic
* public void drive()方法
*2、 声明Car,Bicycle,甚至可以声明Car的各种子类,例如BMW,Benz等
*3、在测试类中创建一个数组,有各种交通工具,遍历调用drive()方法
*/
public class Test01 {
public static void main(String[] args) {
Traffic[] all = new Traffic[3];
all[0]=new Car();
all[1]=new Bicycle();
all[2]=new Car();
all[0].drive();
all[1].drive();
}
}
class Traffic{
public void drive(){
System.out.println("您使用的是");
}
}
class Car extends Traffic{
public void drive(){
System.out.println("私家车");
}
}
class Bicycle extends Traffic{
public void drive(){
System.out.println("自行车");
}
}
练习2
/*
* 1、声明一个Person类,有一个方法
* public void toilet(){
* }
* 2、声明一个Woman。Man类重写方法
* 3、在测试类中声明一个方法
* public static void gotoToilet(Person p){
* 调用toilet方法
* }
*
*/
public class Test02 {
public static void gotoToilet(Person p){
p.toilet();
}
public static void main(String[] args) {
/*
* 另一种方法:
* Woman m = new Woman();
* gotoToile(m);//行参是Person类型,实在是Woman类型
*/
gotoToilet(new Woman());
gotoToilet(new Man());
}
}
class Person{
public void toilet(){
System.out.println("厕所");
}
}
class Woman extends Person{
public void toilet(){
System.out.println("女生去女厕");
}
}
class Man extends Person{
public void toilet(){
System.out.println("男生去男厕");
}
}
数据类型的转换
- 1、基本数据类型的转换
- (1)自动类型转换
- byte->short->int->long->float->double
-
char->
*boolean不参与
*(2)强制类型转换
*double->float->long->int->short->byte
-
->char
- 2、引用数据类型
- 父子类之间的转换:编译期间
- (1)向上转型:从子类-》父类
-
把子类的对象赋值给父类的变量时
-
(方便统一管理各种子类对象)
- (2)向下转型:从父类-》子类
-
把父类的变量赋值给子类的变量时
-
(只有先向上转型的才能向下转型)
*/
public class TestCasting {
public static void main(String[] args) {
//1.向上转型
Person p = new Woman();//多态引用
p.eat();
p.walk();
//向下转型
//想要调用Woman的方法,编译时是Person类型,运行时是Woman类型,编译不通过
Woman m = (Woman)p; //Woman m = p;报错 int i = (int)num;
m.buy();
}
}
class Person{
public void eat(){
System.out.println("吃饭");
}
public void walk(){
System.out.println("走路");
}
}
class Woman extends Person{
public void eat(){
System.out.println("狼吞虎咽");
}
public void walk(){
System.out.println("走小路");
}
public void buy(){
System.out.println("买东西");
}
}
class Man extends Person{
public void eat(){
System.out.println("吃汉堡");
}
public void walk(){
System.out.println("走大路");
}
public void smoke(){
System.out.println("抽烟");
}
}
多态,重载,重写
package demo;
/*
* 考核点:多态,重载,重写
* 1、分析每个类都有什么方法
* A类:
* public String show(D obj)
* public String show(A obj)
* B类:
* public String show(D obj)
* public String show(A obj)重写
* public String show(B obj)
* C类和D类,因为这里没有用它们的对象去调用方法,暂时不分析。
*
* 2、继承关系
* C-->B-->A
* D-->B-->A
*
* 3、如果出现重载的多个方法,会找其中类型最合适的
*
* 4、分析代码
* (1)a1.show(b),因为这里a1没有多态引用,编译时类型和运行时类型都是A类,只看A类的方法。
* 此时b对象是B类型,那么public String show(A obj)这个方法最合适,因为b不能赋值给D子类的形参,只能自动向上转型为A类
*
* (2)a2.show(d),因为这里a2有多态,编译时类型是从A类型中寻找最合适的方法,运行时执行的B类的重写的方法(首先在A类中找到方法,如果B类重写了这个方法,就执行B类的方法),如果B类没有重写,还是执行的是A类的
* 此时d对象是D类型,在A类中public String show(D obj)这个方法最合适。
*
* (3)b.show(c),因为b没有多态,编译时类型和运行时类型都是B类,从B类中选择最合适的方法
* 此时c对象是C类型,在B类中public String show(B obj)最合适的,因为C与B最近,比与A近
*
* (4)b.show(d),因为b没有多态,编译时类型和运行时类型都是B类,从B类中选择最合适的方法
* 此时d对象是D类型,在B类中public String show(D obj)最合适
*/
public class Test01 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("(1)" + a1.show(b));//a1没有多态引用,只看A类,b对象时B类型,b不能赋值给D的形参,只能向上自动转型为A类,public String show(A obj)方法 A and A
System.out.println("(2)" + a2.show(d));//有多态引用,编译时看A类中找最合适的方法,运行时看B类的重写方法,此时B类没有重写 A and D
System.out.println("(3)" + b.show(c));//没有多态引用,只看B类,c对象时C类型,c像转型为B类型 B and B
System.out.println("(4)" + b.show(d));//B中有D类型的方法 A and D
}
}
class A{
public String show(D obj){
return ("A and D");
}
public String show(A obj){
return "A and A";
}
}
class B extends A{
public String show(B obj){
return "B and B";
}
public String show(A obj){
return "B and A";
}
}
class C extends B{
}
class D extends B{
}
结果为:
(1)A and A
(2)A and D
(3)B and B
(4)A and D
package demo2;
public class Test02 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("(1)" + a1.show(b));//a1没有多态,只看A类, A and A
System.out.println("(2)" + a2.show(d));//a2有多态,编译时看A类,运行时看B类 ,A类选择public String show(A obj)方法,
//B类重写了该方法 B and A
System.out.println("(3)" + b.show(c)); //b 没有多态,只看B类,B类有三个方法 public String show(C obj) A and C
System.out.println("(4)" + b.show(d));//b 没有多态,只看B类,B类有三个方法,public String show(B obj) B and B
}
}
class A {
public String show(C obj) {
return ("A and C");
}
public String show(A obj) {
return "A and A";
}
}
class B extends A {
public String show(B obj) {
return "B and B";
}
public String show(A obj) {
return "B and A";
}
}
class C extends B {
}
class D extends B {
}
(1)A and A
(2)B and A
(3)A and C
(4)B and B