java面向对象---三大特性

一、封装

1.封装的概念

封装是把过程和数据包围起来,对数据的访问只能通过已经定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成完全自治、封装的对象,这些对象通过一个受保护的借口访问其他对象。封装是一个信息隐藏技术,在 java 中通过关键字 private ,protected 和 public 实现封装。封装把对象的所有组成部分融合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。适当的封装可以让程式码更容易理解和维护,也加强了程式码的安全性。

java 中对封装的理解:(将某些东西进行隐藏,然后提供相应的方式进行获取)

隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,就是把该隐藏的隐藏起来,该暴露的暴露出来,这就是封装性的设计思想。

2. 封装的好处:提高代码的安全性

3. 代码

package com.mxdx6;

/**
 * @Auther:雨天_
 * @Date: 2022/4/7 - 04 - 07 - 21:40
 * @Descroption: com.mxdx6
 * @version:1.0
 */
public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        Girl g = new Girl();
        /*g.age = 18;
        System.out.println(g.age);
         */
        //设置年龄
        g.shezhiAge(18);
        //读取年龄
        System.out.println(g.duquAge());
    }
}
package com.mxdx6;

/**
 * @Auther:雨天_
 * @Date: 2022/4/7 - 04 - 07 - 21:34
 * @Descroption: com.mxdx6
 * @version:1.0
 */
public class Girl {
    //属性
    private int age;

    //读取年龄
    public int duquAge(){
        return age;
    }
    //设置年龄
    public void shezhiAge(int age){
        if(age >= 30){
            this.age = 18;
        }else{
            this.age = age;
        }
    }
}

 (代码)总结:对于属性 age ,加了修饰符  private ,外界对它的访问受到了限制。属性本身无法再加限制条件,只可通过定义方法加其他的限制条件。

4.以属性为案例进行封装:

(1)将属性私有化,被 private 修饰  -------->加入权限修饰符

一但加入权限修饰符,就不可随意被获取属性

(2)提供 public 修饰的方法可供访问/使用

(3)即使外界可通过方法来访问属性,但是也不可随意访问,因为在方法中也可加入限制条件

5.实际开发中,方法一般会写成getter setter 方法

IDEA的快捷键是: alt+insert ----->Getter and Setter

(1)

package com.mxdx6;

/**
 * @Auther:雨天_
 * @Date: 2022/4/7 - 04 - 07 - 21:34
 * @Descroption: com.mxdx6
 * @version:1.0
 */
public class Girl {
    //属性
    private int age;
    private int sno;
    private String name;
    private double height;

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //读取年龄
    public int getAge(){
        return age;
    }
    //设置年龄
    public void setAge(int age){
        if(age >= 30){
            this.age = 18;
        }else{
            this.age = age;
        }
    }

}

(2)

package com.mxdx7;

/**
 * @Auther:雨天_
 * @Date: 2022/4/11 - 04 - 11 - 21:39
 * @Descroption: com.mxdx7
 * @version:1.0
 */
public class Student {
    //属性
    private int age;
    private String name;
    private String sex;

    //加入对应的getter和setter方法

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        if ("男".equals(sex) || "女".equals(sex)){//sex判断男女
            this.sex = sex;
        }else{
            this.sex = "男";
        }
    }
    //加入构造器
    public Student(){

    }
    public Student(int age,String name,String sex){
        this.name = name;
        //this.sex = sex;
        this.setSex(sex);
        this.age = age;

    }
}
package com.mxdx7;

/**
 * @Auther:雨天_
 * @Date: 2022/4/11 - 04 - 11 - 21:39
 * @Descroption: com.mxdx7
 * @version:1.0
 */
public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个Student对象
        Student s1 = new Student();
        s1.setAge(19);
        s1.setName("大聪明");
        s1.setSex("女");
        System.out.println(s1.getSex()+"-----"+s1.getName()+"-----"+s1.getAge());

        Student s2 = new Student(18,"大微微","aadadaa");
        System.out.println(s2.getSex()+"-----"+s2.getName()+"-----"+s2.getAge());
    }
}

二、继承

【1】概念

1.类是对象的抽象,继承是对类的抽象。

由继承得到的类被称为子类(派生类),被继承的类成为父类(超类)。 

2,概念:吸收现有的类的数据和行为,附属新功能,创建新类。

3.继承的好处:提高代码的复用性 

4.代码演示:

先写父类,再写子类:

父类:Person 

子类:Student

package com.mxdx8;

/**
 * @Auther:雨天_
 * @Date: 2022/4/13 - 04 - 13 - 13:24
 * @Descroption: com.mxdx8
 * @version:1.0
 */
public class Person {
    //属性
    private int age;
    private String name;
    private double height;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    //方法

    public void eat(){
        System.out.println("喜欢吃饭");
    }

    public void sleep(){
        System.out.println("喜欢睡觉");
    }

}
package com.mxdx8;

/**
 * @Auther:雨天_
 * @Date: 2022/4/13 - 04 - 13 - 13:24
 * @Descroption: com.mxdx8
 * @version:1.0
 */
public class Student extends Person {// java 中的继承是通过 extends 来实现的
    //属性
    private int sno;

    public int getSno() {
        return sno;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }
    //方法:
    public void lie(){
        System.out.println("被骗了十块钱");
    }
}
package com.mxdx8;

/**
 * @Auther:雨天_
 * @Date: 2022/4/13 - 04 - 13 - 13:36
 * @Descroption: com.mxdx8
 * @version:1.0
 */
public class Test {
    //这是一个main方法
    public static void main(String[] args) {
        //创建子类的 Student 的对象
        Student s1 = new Student();
        s1.setSno(0303);
        s1.setAge(20);
        s1.setHeight(175.2);
        s1.setName("菲菲");

        System.out.println("学生的名字为:"+s1.getName()+",学生的年纪为:"+s1.getAge()+",学生的身高为:"+s1.getHeight());

        //访问方法
        s1.lie();
        s1.eat();
        s1.sleep();
    }
}

PS:父类 privite 修饰的内容,子类也继承。只是封装的特性阻碍了直接调用,但是也提供了间接调用的方式。

 5.总结

(1)继承关系:子类继承父类是在一定关系范围内继承的

(2)继承的好处:

提高了代码的复用性(父类的内容,子类直接用);便于代码的扩展;是多态的前提

(3)一个父类可以有多个子类;一个子类只能有一个直接父类(可以间接的继承自其他类)。

(4)继承具有传递性:Object 是所有类的根基父类。所有累都直接或者间接的继承自 Object 。

【2】  权限修饰符

 (1)privite:权限:在当前类中可以访问

package com.mxdx5;

public class Test01 {
    private int age;//未添加Setter Getter 方法,不可以在不同类中访问

    public void eat(){
        System.out.println(age);
        age = 10;
    }

}
package com.mxdx5;

public class A {
    //这是一个main方法
    public static void main(String[] args) {
        A a1 = new A();
        a1.age(10);//不同类中不可以访问
    }
}

 (2)default(缺省修饰符):权限:同一个包下的其他类都可以访问

package com.mxdx5;

public class A {
    int age;//default 一般不写,写了就出错

    public void eat(){
        System.out.println(age);
        age = 10;
    }
}
package com.mxdx5;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        A a1 = new A();
        a1.age = 10;
    }
}

(3)project:权限:最大到不同包下的子类

package com.mxdx5;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        A a1 = new A();
        a1.age = 10;
    }
}
package com.mxdx5;

public class A {
    protected int age;

    public void eat(){
        System.out.println(age);
        age = 10;
    }
}
package com.mxdx6;

import com.mxdx5.A;

public class B extends A {//不同包下的子类依旧可以访问
    public void a(){
        System.out.println(age);
    }
}

 (4)public:权限:在整个项目中都可以访问

package com.mxdx5;

public class A {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void eat(){
        System.out.println(age);
        age = 10;
    }
}

 权限修饰符总结:

        属性和方法:修饰符:privite  default  project  public  

        类:修饰符:两种:default  public 

PS:

一般属性:用 privite 来修饰   

方法:用 public 来修饰

【3】方法的重写

1.重写的发生:

发生在子类和父类中,子类对父类提供的方法不满意的时候,对父类方法进行重写。

2.重写的格式要求:

子类的方法名字和父类的必须一致,参数列表(个数,顺序,类型)也要和父类一致

3.代码:

package com.mxdx6;


public class Person {
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}
package com.mxdx6;

public class Student extends Person{
    public void study(){
        System.out.println("学习");
    }
    public void sleep(){
        System.out.println("不睡觉");
    }
}
package com.mxdx6;

public class Test02 {
    //这是一个main方法
    public static void main(String[] args) {
        Student s = new Student();

        s.sleep();
    }
}

4.内存:

5.重载和重写的区别

重载同一个类中,方法名相同,形参列表不同的时候,多个方法构成了重载

重写在不同类中,子类对父类提供的方法不满意的时候,对父类的方法进行重写 

 

 【4】super

1.super . 指的是:父类的

2.super 可以修饰属性,也可以修饰方法:在子类的方法中,可以通过 super . 方法/属性显示来调用父类提供的方法/属性。(通常不写)

 在特殊情况下:当子类和父类的方法/属性重名时,想使用父类的方法/属性时,必须加上super. ,只可通过super 方法/属性来调用

package com.mxdx2;

public class Person01 {
    int age = 22;
    public void eat(){
        System.out.println("吃饭");
    }
}
package com.mxdx2;
public class Student extends Person01{
    double score;
    int age = 11;
    public void study(){
        System.out.println("学习");
    }

    public void eat(){
        System.out.println("吃米饭");
    }
    public void m(){
        System.out.println(age);
        System.out.println(this.age);
        System.out.println(super.age);
        eat();
        this.eat();
        super.eat();
    }
}
package com.mxdx2;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个Student的具体的对象
        Student s1 = new Student();
        s1.m();
    }
}

 3.super 修饰构造器

(1)(平时写空构造器第一行都有:super.----->作用:调用父类的空构造器,一般不写)

 

(2)如果构造器中显示已经调用super父类构造器,那么第一行就没有默认分配的super();了 

(若构造器中显示的使用super();调用了父类构造器,那么super();就不会默认分配构造器了。)

 (3)构造器中,super调用父类构造器和this调用子类构造器只能存在一个,两者不能共存。super构造器放在第一行,this构造器也放在第一行。

 (4)在IDEA 中生成构造器的快捷键是:alt + insert----->constructer

附:继承条件下构造方法的执行过程:

 (代码展示)

package com.mxdx4;

public class Person01 {
    int age;
    String name;

    public Person01() {

    }

    public Person01(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
package com.mxdx4;

public class Student extends Person01{
    double height;

    public Student() {

    }

    public Student(double weight) {
        this.height = height;
    }

    public Student(int age, String name, double height) {
        super(age, name);
        this.height = height;
    }
}
package com.mxdx4;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        Student s = new Student(19,"feifei",160.8);

    }
}

【5】object

1.概念

所有类都直接或者间接的继承自Object类,Object类是所有java 类的根基类;意味着所有 java 对象都拥有 Object 类的属性和方法。若在类的声明中未使用 extends 指明其父类,则默认继承Object类。

2.toString() 方法

(1)Object 类的toString() 方法的作用

 (2)(方法的原理

(3)使用 toString()  方法的时候,可读性不好。

例如:

package com.mxdx;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个Person01类的具体的实例
        Person01 p1 = new Person01(19,"dd",160.7);
        System.out.println(p1);//com.mxdx.Person01@1b6d3586
        System.out.println(p1.toString());//com.mxdx.Person01@1b6d3586
    }
}

子类 Person01 对父类 Object 的 toString 方法不满意  ----> 对 toString 方法进行重写

package com.mxdx;

public class Person01 {
    private int age;
    private String name;
    private double height;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public Person01() {

    }

    public Person01(int age, String name, double height) {
        this.age = age;
        this.name = name;
        this.height = height;
    }

    public String toString(){
        return "这是一个 Person01 对象,这个对象的名字是:"+name+",年龄是:"+age+",身高是:"+height;
    }
}
package com.mxdx;

public class Test01 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个Person01类的具体的实例
        Person01 p1 = new Person01(19,"dd",160.7);
        System.out.println(p1);
        System.out.println(p1.toString());
    }
}

(4)总结:toString() 方法的作用就是对对象进行自我介绍,一般子类对父类提供的 toString() 方法都不满意,都得进行重写。

(5)IDEA 快捷键:alt + insert ------> toString()

3.equals

(1)作用:是对对象内容是否相等的比较方式,对象内容指的就是的属性

父类Object 提供的 equals 在比较地址,没有实际意义,一般不会使用父类提供的方法,而是在子类中对方法进行重写。

代码插入:

package com.mxdx;

/**
 * @Auther:雨天_
 * @Date: 2022/4/13 - 04 - 13 - 20:48
 * @Descroption: com.mxdx
 * @version:1.0
 */
public class Phone {
    //属性
    private String brand;
    private double price;
    private int year;
    //方法

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    //构造器

    public Phone() {

    }

    public Phone(String brand, double price, int year) {
        this.brand = brand;
        this.price = price;
        this.year = year;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                ", year=" + year +
                '}';
    }

    //对equals方法进行重写
    public boolean equals(Object obj){
        //将 Obj 转为 Phone 类型:
        Phone other = (Phone) obj;
        if(this.getBrand()==other.getBrand()&&this.getPrice()==other.getPrice()&&this.getYear()==other.getYear()){
            return true;
        }
        return false;
    }
}
package com.mxdx;

/**
 * @Auther:雨天_
 * @Date: 2022/4/13 - 04 - 13 - 20:52
 * @Descroption: com.mxdx
 * @version:1.0
 */
public class Test02 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个 Phone 类的对象
        Phone p = new Phone("huaweimate30",4099,2019);
        Phone p1 = new Phone("huaweimate30",4099,2019);
        //比较:
        //==的作用:比较两边的值是否相等。相等返回true,不相等返回false
        System.out.println(p==p1);//引用数据类型比较的是地址值,一定不相等,返回false

        //Object中equals 方法:作用:比较对象具体内容是否相等
        boolean flag = p.equals(p1);//点进源码,底层比较依旧是==,比较地址值
        System.out.println(flag);
    }
}

 (2)instanceof(运算符)

(3)利用集成开发工具生成 equals 方法

eclipse:

IDEA:

//    //对equals方法进行重写
//    public boolean equals(Object obj){
//        /*
//        *  a  instanceof b
//        * 判断 a 对象是否是 b 这个类的实例,是返回 true ,不是返回 false
//        * */
//        if(obj instanceof Phone){//属于 Phone 类的对象
//            //将 Obj 转为 Phone 类型:
//            Phone other = (Phone) obj;//原因:??
//            if(this.getBrand()==other.getBrand()&&this.getPrice()==other.getPrice()&&this.getYear()==other.getYear()){
//                return true;
//            }
//        }
//        return false;
//    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Phone phone = (Phone) o;
        return Double.compare(phone.price, price) == 0 && year == phone.year && Objects.equals(brand, phone.brand);
    }

    @Override
    public int hashCode() {
        return Objects.hash(brand, price, year);
    }

 【6】类和类之间的关系

1.代码展示:

package com.mxdx5;

public class Girl {
    //属性
    int age;
    double weight;
    String name;
    //方法
    public void watch(int d){//基本数据类型
        System.out.println(d);
        System.out.println(d + 100);
    }
    //谈恋爱的方法
    public void love(Boy t){//引用数据类型
        System.out.println("我男朋友的名字叫:"+t.name+"他的年龄是"+t.age);
        t.good();
    }
    //构造器
    
    public Girl(int age, double weight, String name) {
        this.age = age;
        this.weight = weight;
        this.name = name;
    }
}
package com.mxdx5;

public class Boy {
    //属性
    int age;
    String name;
    //方法
    public void good(){
        System.out.println("恋爱了我会一直对你好");
    }
    //构造器

    public Boy(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
package com.mxdx5;

public class Test02 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个 Boy 类的具体的对象
        Boy tqw = new Boy(19,"tqw");
        //创建一个 Girl 类的具体的对象
        Girl wyd = new Girl(19,120.4,"wyd");
        //恋爱
        wyd.love(tqw);
    }
}

(1)面向对象的思维:找参与者。 ( 男孩和女孩类)

(2)方法的形参和方法的实参

 (3)类和类可以产生关系

将一个类作为另一个类中方法的形参;将一个类作为另一个类的属性

package com.mxdx5;

public class Girl {
    //属性
    int age;
    double weight;
    String name;
    Mom m /*= new Mom()*/;
    //方法
    public void watch(int d){//基本数据类型
        System.out.println(d);
        System.out.println(d + 100);
    }
    //谈恋爱的方法
    public void love(Boy t){//引用数据类型
        System.out.println("我男朋友的名字叫:"+t.name+"他的年龄是"+t.age);
        t.good();
    }
    //女孩和妈妈聊天
    public void wechat(){
        m.talk();
    }
    //构造器

    public Girl(int age, double weight, String name) {
        this.age = age;
        this.weight = weight;
        this.name = name;
    }
}
package com.mxdx5;

public class Boy {
    //属性
    int age;
    String name;
    //方法
    public void good(){
        System.out.println("我会一直对你好");
    }
    //构造器
    public Boy(int age, String name) {
        this.age = age;
        this.name = name;
    }
}
package com.mxdx5;

public class Mom {
    public void talk(){
        System.out.println("妈妈爱说好多事");
    }
}
package com.mxdx5;

public class Test02 {
    //这是一个main方法
    public static void main(String[] args) {
        //创建一个 Boy 类的具体的对象
        Boy tqw = new Boy(19,"tqw");
        //创建一个 Girl 类的具体的对象
        Girl wyd = new Girl(19,120.4,"wyd");
        //恋爱
        wyd.love(tqw);

        //女孩和妈妈微信聊天
        wyd.m = new Mom();
        wyd.wechat();
    }
}

2.分类

(1)继承关系:继承指的是一个类(子类,子接口)继承另外的一个类(父类,父接口)的功能,并增加自己新功能的能力。在 java 中用 extends 明确标识,一般不具有争议性。

(2)实现关系:实现指的是一个 class 实现 interface 接口,实现是接口与类之间最常见的关系。在 java 中用 implements 明确标识。一般不具有争议性。

(3)依赖关系:依赖就是一个类 A 使用到了另一个类 B ,这种使用关系是偶然的、临时性的、非常弱的,但是类 B 的变化会影响到类 A 。表现在代码层面,让类 B 作为参数被类 A 在某个 method 方法中使用。

(4)关联关系:关联体现的是两个类之间语义级别的一种强依赖关系。不存在依赖关系的偶然性,关系也不是临时的,一般是长期性的,双方的关系一般是平等的,关联可以是单向、双向的。表现在代码层面,为被关联类 B 以类的属性形式出现在关联类 A 中,也可能是关联类 A 引用了一个被关联类 B 的全局变量。

(5)聚合关系:聚合是关联关系的一种特例,它体现的是整体与部分的关系,即 has-a 的关系。此时整体与部分是可分离的,它们可以具有各自的生命周期,部分可属于多个整体对象,也可为多个整体对象共享。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

(6)组合关系:组合也是关联关系的一种特例,它体现的是一种 contains-a 的关系,这种关系比聚合更强,也称强聚合。它同样体现整体与部分的关系,但此时整体与部分是不可分的,整体的生命周期结束也意味着部分生命周期的结束。表现在代码层面,和关联关系是一致的,只能从语义级别来区分。

-------------------------------------------------------------------------------------------------------------------------------

总结:继承和实现它们体现的是一种类和类、类和接口之间的纵向关系。其他四种关系体现的是一种类和类、或者类和接口之间的引用、横向关系,是比较难区分的。这四种关系都是语义级别的,所以从代码层面不能完全区分各种关系。

后四种关系表现的强弱程度依次是:组合>聚合>关联>依赖

三、多态

1.关系:多态与属性无关,多态指的是方法的多态,而不是属性的多态。

2.(代码分析)

package com.mxdx1;

public class Animal {
    public void shout(){
        System.out.println("我是小动物,我会叫");
    }
}
package com.mxdx1;

public class Girl {
    //女孩和猫玩
    public void play(Cat cat){
        cat.shout();
    }

    //女孩和狗玩
    public void play(Dog dog){
        dog.shout();
    }
    //女孩和小动物玩
    public void play(Animal an){
        an.shout();
    }
}
package com.mxdx1;

public class Dog extends Animal{
    public void shout(){
        System.out.println("我是狗,我会汪汪");
    }

    public void guard(){
        System.out.println("我会看好主人家的院子");
    }
}
package com.mxdx1;

public class Tiger extends Animal{
    public void eat(){
        System.out.println("我是老虎,我吃肉");
    }

    public void shout(){
        System.out.println("我是老虎,我吼叫");
    }
}
package com.mxdx1;

public class Cat extends Animal{
    public void shout(){
        System.out.println("我会喵喵叫");
    }

    public void jump(){
        System.out.println("我跳得高");
    }
}
package com.mxdx1;

public class Test {
    //这是一个main方法
    public static void main(String[] args) {
        //具体的猫
        Cat c = new Cat();
        //具体的小女孩
        Girl g = new Girl();
        //小女孩和猫玩
        g.play(c);
        //具体的狗
        Dog d = new Dog();
        //小女孩和狗玩
        g.play(d);
        //具体的小动物
        Tiger ti = new Tiger();
        Animal a =ti;
        //小女孩和小动物玩
        g.play(a);
    }
}

(内存分析)

3.总结

(1)先有父类,再有子类 -------> 继承     先有子类,再有父类 -------->泛化

(2)什么是多态:多态指的是就是多种状态,同一个行为,不同的子类表现出来不同的状态。同一个方法调用,对象不同产生不同的行为

(3)多态的好处:为了提高代码的拓展性,符合面向对象的设计原则:开闭原则。

(开闭原则:指的是拓展是开放的,修改是关闭的。)

PS : 多太态可以提高拓展性,但是拓展性不是最好。(反射

(4)多态的三个要素:继承、重写、父类引用指向子类对象

例:

//(父类引用指向子类对象)
Tiger ti = new Tiger();
Animal a = ti;

//合为一句
Animal a = new Tiger();
/*
=左侧  编译期类型
=右侧  运行期类型
*/

public void play(Animal an){//Animal an = an = new Tiger
        an.shout();
    }

/*
上面代码也是非常常见的应用场合:父类当方法的形参,传入的是具体的子类的对象,调用同一个方法,
根据传入的字类不同展现出来的效果也不同,构成了多态。
*/

4.向上转型和向下转型

 

public class Demo {
    //这是一个main方法
    public static void main(String[] args) {
        Cat c = new Cat();
        Animal a = c;
        a.shout();

        a.jump();//报错
    }
}

 将访问 weight 和 jump 属性:

public class Demo {
    //这是一个main方法
    public static void main(String[] args) {
        Cat c = new Cat();
        Animal a = c;//转型:向上转型
        a.shout();

        //加入转型的代码
        //将Animal转为Cat类型
        Cat cat = (Cat) a;//转型:向下转型
        cat.jump();
        cat.shout();
        cat.weight = 90;

        //a.weight = 90;
        //a.jump();
    }
}
Cat cat = (Cat) a;//对应内存分析

 5.简单工厂模式

        不仅可以使用父类做方法的形参,也可使用父类做方法的返回值类型,真是返回的对象可以是该类的任意一个子类对象。

简单工厂模式的实现,解决大量对象创建问题的一个解决方案,将创建和使用分开,工厂负责创建,使用直接调用即可。基本要求是:

(1)定义一个 static 方法,通过类名直接调用

(2)返回值类型是父类类型,返回的可以是任意其子类类型

(3)传入一个字符串类型的参数,工厂根据参数创建对应的子产品

代码示例:

package com.mxdx1;

public class Petstore {
    public static Animal getAnimal(String name ){//多态的应用场合(二)
        Animal a = null;
        if("狗".equals(name)){//Name.equals("狗")--->这样写容易发生空指针异常
            a = new Dog();
        }

        if("猫".equals(name)){
            a = new Cat();
        }

        if("老虎".equals(name)){
            a = new Tiger();
        }

        return a;

    }
}
package com.mxdx1;

public class Test {
    //这是一个main方法
    public static void main(String[] args) {

        //具体的小女孩
        Girl g = new Girl();

        //Tiger ti = new Tiger();
        Animal a =Petstore.getAnimal("狗");
        //小女孩和小动物玩
        g.play(a);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨天_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值