面向对象03

Posted jaro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象03相关的知识,希望对你有一定的参考价值。

1.多态

所谓多态就是事物存在的多种形态
表现形式是父类引用指向子类对象
多态前提:
* a:要有继承关系
* b:要有方法重写
* c:要有父类引用指向子类对象
重写:
就是子类中写了和父类相同的方法,将父类方法覆盖
这样子类在调用该方法时,就直接调用自己的方法,而不是父类的方法
案例:

 1 class Demo1_Polymorphic {
 2     public static void main(String[] args) {
 3         Cat c = new Cat();
 4         c.eat();
 5 
 6         Animal a = new Cat();
 7                 //创建一个动物,这个动物是只猫,这没问题,父类引用指向子类对象
 8         a.eat();//这里结果是猫吃鱼
 9     }
10 }
11 class Animal {
12     public void eat() {
13         System.out.println("动物吃饭");
14     }
15 }
16 
17 class Cat extends Animal {
18     public void eat() {
19         System.out.println("猫吃鱼");
20     }
21 }

看看下面的例子:

 1 class SuperMan extends Person {
 2     String name = "superMan";
 3 
 4     public void talkTrade() {
 5         System.out.println("谈几个亿的大单子");
 6     }
 7 
 8     public void fly() {
 9         System.out.println("飞出去救人");
10     }
11 }
1 public class Person {
2     String name = "John";
3     public void talkTrade() {
4         System.out.println("谈生意");
5     }
6 }
 1 public class Demo3_SuperMan {
 2     public static void main(String[] args) {
 3         Person p = new SuperMan();//向上转型
 4         System.out.println(p.name);//没有用到多态,调用的是父类的属性        
 5         p.talkTrade();//只有这里用到了多态,因为只有这里运用的是重写的方法
 6         //p.fly(),能这样写吗?是不能的,因为超人被提升为人了,而父类是不能调用子类方法的,这里p是父类对象,只有当满足多态条件时,才会看成子类对象
 7         SuperMan sm = (SuperMan)p;//向下转型
 8         sm.fly();
 9     }
10 }

运行结果:

John
谈几个亿的大单子
飞出去救人

为什么会出现这个结果,注释中解释了

2.多态中向上转型和向下转型

Person p = new SuperMan();向上转型,超人提升为人,为什么叫向上转型,因为人是父类,是在上的
SuperMan sm = (SuperMan)p;向下转型,人转换为子类超人
3.多态的好处和弊端
* A:多态的好处
* a:提高了代码的维护性(继承保证)
* b:提高了代码的扩展性(由多态保证)
* B:案例演示
* 多态的好处
* 可以当作形式参数,可以接收任意子类对象,就是在方法中使用父类作为参数时,有时会用到多态
* C:多态的弊端
* 不能使用子类的特有属性和行为,上面代码已经演示了
 1     public static void method(Animal a) {    
 2                 //当作参数的时候用多态最好,因为扩展性强
 3                 //当传入对象是猫或者狗的时候,实际上Animal a = 猫,所以用到多态了
 4         //关键字 instanceof 判断前边的引用是否是后边的数据类型
 5         if (a instanceof Cat) {
 6             Cat c = (Cat)a;
 7             c.eat();
 8             c.catchMouse();
 9         }else if (a instanceof Dog) {
10             Dog d = (Dog)a;
11             d.eat();
12             d.lookHome();
13         }else {
14             a.eat();
15         }
16     }    

4.关键字abstract

意为抽象,就是看不懂,你不知道
* a:抽象类和抽象方法必须用abstract关键字修饰
* abstract class 类名 {}
* public abstract void eat();//不知道该方法具体是怎么实现的
//比如动物吃,你知道它吃什么吗?怎么吃?都不知道
* b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
* c:抽象类不能实例化那么,抽象类如何实例化呢?
* 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态
* d:抽象类的子类
* 要么是抽象类
* 要么重写抽象类中的所有抽象方法

 1 abstract class Animal {                        //抽象类
 2     public abstract void eat();                //抽象方法,子类继承抽象类,抽象方法是强制要重写的,和接口一样,不重写,抽象还有什么意义
 3     public Animal() {
 4         System.out.println("父类空参构造");
 5     }
 6 }
 7 class Cat extends Animal {
 8     public Cat() {
 9         super();
10     }
11 
12     @Override
13     public void eat() {
14         // TODO Auto-generated method stub
15         System.out.println("mao ci yu");
16     }
17 }
18 class Demo1_Abstract {
19     public static void main(String[] args) {
20         //Animal a = new Animal();            //错误: Animal是抽象的; 无法实例化
21         Animal a = new Cat();                //父类引用指向子类对象
22         a.eat();
23     }
24 }

运行结果:

父类空参构造

mao ci yu

抽象类的成员特点:
* A:抽象类的成员特点
* a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员变量
* b:构造方法:有
* 用于子类访问父类数据的初始化
* c:成员方法:既可以是抽象的,也可以是非抽象的
* B:案例演示
* 抽象类的成员特点
* C:抽象类的成员方法特性:
* a:抽象方法,强制要求子类做的事情。
* b:非抽象方法,子类继承的事情,提高代码复用性

 1 abstract class Demo {
 2     int num1 = 10;//变量
 3     final int num2 = 20;//常量
 4 
 5     public Demo(){}//构造方法
 6 
 7     public void print() {//非抽象方法,子类可以直接使用
 8         System.out.println("我是码农");
 9     }
10 
11     public abstract void method();//抽象方法,子类必须实现
12 }
13 
14 class Test extends Demo {
15     public void method() {
16         System.out.println("绝地求生");
17     }
18 }

* A:面试题1
* 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以
* 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
* B:面试题2
* abstract不能和哪些关键字共存
不能与static,final,final共存
abstract和static
被abstract修饰的方法没有方法体
被static修饰的可以用类名.调用,但是类名.调用没有实现的抽象方法有什么意义
abstract和final
被abstract修饰的方法强制子类重写
被final修饰的不让子类重写,所以他俩是矛盾
abstract和final
被abstract修饰的是为了让子类看到并强制重写
被private修饰不让子类访问,子类都不能访问了,还重写个啥啊

5.接口:

* A:接口概述
* 从狭义的角度讲就是指java中的interface
* 从广义的角度讲对外提供规则的都是接口
* B:接口特点
* a:接口用关键字interface表示
* interface 接口名 {}
* b:类实现接口用implements表示
* class 类名 implements 接口名 {}
* c:接口不能实例化
* 那么,接口如何实例化呢?
* 按照多态的方式来实例化
* d:接口的子类
* a:可以是抽象类。但是意义不大
* b:可以是具体类。要重写接口中的所有抽象方法,代码中无处不在
* A:接口成员特点
* 成员变量只能是常量,并且是静态的并公共的
* 默认修饰符:public static final
* 构造方法:接口没有构造方法
* 成员方法:只能是抽象方法
* 默认修饰符:public abstract

1 public interface Inter {
2     public static final int num = 10;//这里写不写public static final都会默认加上
3     public abstract void print();//这里写不写public abstract都会默认加上,因为写接口本来就是为了实现的啊,会默认加上abstract
4 }
1 class Demo implements Inter {
2     public Demo() {
3         super();
4     }
5     public void print() {
6         //num = 20;num已经被final修饰了,不能重新赋值
7         System.out.println(num);
8     }
9 }
1 public class Demo2_Interface {
2     public static void main(String[] args) {
3         Demo d = new Demo();
4         d.print();
5         System.out.println(Inter.num);
6     }
7 }

运行结果:

10
10

类与类,类与接口,接口与接口的关系:
* A:类与类,类与接口,接口与接口的关系
* a:类与类:
* 继承关系,只能单继承,可以多层继承
* b:类与接口:
* 实现关系,可以单实现,也可以多实现
* 并且还可以在继承一个类的同时实现多个接口
* c:接口与接口:
* 继承关系,可以单继承,也可以多继承

抽象类和接口的区别:

两者都会用到关键字abstract ,有什么区别呢

* A:成员区别
* 抽象类:
* 成员变量:可以变量,也可以常量
* 构造方法:有
* 成员方法:可以抽象,也可以非抽象
* 接口:
* 成员变量:只可以常量
* 成员方法:只可以抽象

在接口中变量和方法都作了限制

设计理念上的区别
* 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能,是为了给子类根据自身需要,重写重写抽象方法,所以抽象类是共性功能的提取
* 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能,也就是说要扩展的时候常写一个接口,如果想要该功能就去实现这个接口
* 对事物本质的抽象用抽象类,对事物功能的扩展用接口

看看下面代码就明白了:

 1 abstract class Animal {
 2     private String name;                
 3     private int age;                    
 4     public Animal() {}                    
 5     public Animal(String name,int age) {
 6         this.name = name;
 7         this.age = age;
 8     }
 9 
10     public void setName(String name) {
11         this.name = name;
12     }
13 
14     public String getName() {            
15         return name;
16     }
17 
18     public void setAge(int age) {        
19         this.age = age;
20     }
21 
22     public int getAge() {                
23         return age;
24     }
25     public abstract void eat();        
26     public abstract void sleep();    
27 }
 1 class Cat extends Animal {
 2     public Cat() {}                    
 3     public Cat(String name,int age) {
 4         super(name,age);
 5     }
 6     public void eat() {
 7         System.out.println("猫吃鱼");
 8     }
 9     public void sleep() {
10         System.out.println("侧着睡");
11     }
12 }
1 interface Jumping {    
2     public void jump();
3 }
1 class JumpCat extends Cat implements Jumping {
2     public JumpCat() {}
3     public JumpCat(String name,int age) {
4         super(name,age);
5     }
6     public void jump() {
7         System.out.println("猫跳高");
8     }
9 }
 1 public class Test1_Animal {
 2     public static void main(String[] args) {
 3         Cat c = new Cat("加菲",8);
 4         c.eat();
 5         c.sleep();
 6         JumpCat jc = new JumpCat("跳高猫",3);
 7         jc.eat();
 8         jc.sleep();
 9         jc.jump();
10     }
11 }

运行结果:

猫吃鱼
侧着睡
猫吃鱼
侧着睡
猫跳高

现在看看这些面向对象中的设计,都是有道理的,都是观察现实中的事物,然后抽取出来的

为实现不同的功能而设计的

Java语言,不管是什么编程语言,这些设计者是真的厉害

 

 

 
 
 
 

 

以上是关于面向对象03的主要内容,如果未能解决你的问题,请参考以下文章

Java面向对象03

面向面试编程代码片段之GC

PHP面向对象之选择工厂和更新工厂

Java中面向对象的三大特性之封装

03-面向对象封装案例

python之路之前没搞明白4面向对象(封装)