面向对象

  • 一、面向对象
    • 1、面向过程
    • 1.2、举例
    • 1.3、总结
  • 二、面向对象
    • 1、简述
    • 2、举例
    • 3、思想特点
    • 2.1、类的定义格式
      • 2.1.1、简述
      • 2.2.2、格式
      • 2.3.3、示例
  • 三、类的使用
  • 四、封装
    • 4.1标准代码
    • 4.2 封装的概述和好处
    • 4.3、好处
    • 4.4、this关键字
  • 五、构造方法
    • 5.1、概述
    • 5.2、格式
    • 5.3、示例: 构造方法入门
  • 六 继承
    • 概念
    • 继承的优劣
    • 继承中成员变量访问特点
    • super关键字
  • 七、继承中构造方法的特点
  • 对构造方法的总结
  • 八、继承中成员方法的特点
    • 示例
  • 九、方法重写
    • 老师和学生案例(继承版)
  • 十 多态
    • 1、概述
    • 2、前提条件
    • 3、示例: 多态入门
    • 2多态中的成员访问特点
      • 好处和弊端.
        • 好处
        • 弊端
      • 例题3
    • 向上转型和向下转型
      • 向上转型
      • 向下转型
      • 例题4

苟有恒,何必三更眠五更起; 最无益,莫过一日曝十日寒。

一、面向对象

1、面向过程

​ 1.1、简述
我们回想一下, 前面我们完成一个需求的步骤是怎样的?
​ 首先是搞清楚我们要做什么
然后在分析怎么做
最后我们在通过代码一步一步去实现
上述的每一个步骤, 我们都是参与者, 并且需要面对具体的每一个步骤和过程, 这就是面向过程最直接的体现

1.2、举例

​ 生活中的例子: 洗衣服
​ 想完成洗衣服这个需求, 需要完成下述的每一个步骤:

  1. 找个盆
  2. 接点水
  3. 到洗衣液
  4. 把衣服放进去浸泡10分钟
  5. 把衣服揉搓干净
  6. 漂洗
  7. 拧干水分
  8. 晾晒
    注意:
    上述的这些步骤, 但凡有一个我们不会做, 就没有办法完成洗衣服这个需求
    每一步都需要我们亲自做, 这就是: 面向过程思想

代码举例: 把数组元素按照指定格式进行输出
数组:int arr={11,22,33,44,55}; 输出格式:[11, 22, 33, 44, 55]

  1. 定义方法printArray(), 参数列表为: int[] arr, 返回值的类型为String
  2. 定义字符串变量s, 用来记录数组元素拼接后的结果
  3. 字符串变量s的初始化值设置为[
  4. 对数组对象进行判断, 看其是否是合法对象 (即: 数组对象不为null)
  5. 通过for循环遍历数组, 获取到每一个元素
  6. 判断当前获取到的元素是否是最后一个元素, 并和字符串变量s进行拼接
    如果是最后一个元素, 则在后边在拼接上]
    如果不是最后一个元素, 则在后边在拼接上
  7. 当for循环执行结束后, 字符串变量s记录的就是拼接后的结果, 将其直接返回即可
    注意: 上述的每一步代码都需要我们编写, 这样做比较繁琐

1.3、总结

面向过程思想其实就是一种编程思想。所谓的面向过程开发, 指的就是面向着具体的每一个步骤和过程, 把每一个步骤和过程完成, 然后由这些功能方法相互调用, 完成需求
面向过程的代表语言: C语言

二、面向对象

1、简述

当需求单一, 或者简单时, 我们一步一步去操作是没问题的, 并且效率也挺高。
可随着需求的更改, 功能的增多, 发现需要面对每一个步骤就很麻烦了, 于是我们就想着, 能不能把这些步骤和功能在进行封装, 封装时根据不同的功能, 进行不同的封装, 功能类似的用一个类封装在一起, 这样结构就清晰了很多。用的时候, 找到对应的类就可以了。 这就是面向对象的思想。

2、举例

生活中的例子: 洗衣服

  1. 想完成洗衣服这个需求, 我们可以通过洗衣机来实现
  2. 对于我们来讲, 洗衣机就是我们的对象

​ 代码举例: 把数组元素按照[11, 22, 33, 44, 55]的格式进行输出
​ 上述的需求, 我们可以通过Arrays类的toString()方法来实现
int[] arr = {11, 22, 33, 44, 55};
System.out.println(Arrays.toString(arr)); //结果:[11, 22, 33, 44, 55]

3、思想特点

​ 是一种符合我们思考习惯的思想
​ 可以将复杂的事情简单化
​ 让我们从执行者变成了指挥者
​ 2.4、总结
面向对象思想是一种编程思想, 它是基于面向过程的, 强调的是以对象为基础完成各种操作。

⦁ 二、类和对象
⦁ 1、对象
面向对象的思想就是把一切都看成对象
对象就是现实世界中存在的事物。事物都有着自己独特的个性
学习编程的目的,就是为了把现实世界的事物通过代码模拟出来,实现信息化。
例如: 超市的收银系统
现实世界的事物:收银员、商品
刚才我们提到,事物都有自己独特的个性:属性、行为
属性:就是对象的特征(有什么)
行为:就是对象的功能(干什么)

具有相同属性的对象称为类。是个抽象的概念

2.1、类的定义格式

2.1.1、简述

Java语言最基本的单位是类。
定义类其实就是定义类的成员(成员变量和成员方法)
⦁ 成员变量(属性):
⦁ 和以前定义变量是一样的, 只不过位置发生了改变, 写到类中, 方法外
⦁ 而且成员变量还可以不用赋值, 因为它有默认值.
⦁ 成员方法(行为):
⦁ 和以前定义方法是一样的, 只不过把static关键字去掉.
⦁ 这点先记忆即可, 后面我们再讲解static关键字的用法.

2.2.2、格式

public class 类名 {
//成员变量
//成员方法
}

2.3.3、示例

需求
定义一个学生类.
参考代码
public class Student{
//成员变量, 就是属性.
String name; //姓名
int age; //年龄

//成员方法, 就是行为
//学习的方法
public void study() {System.out.println("键盘敲烂, 月薪过万!...");
}//吃饭的方法
public void eat() {System.out.println("学习饿了要吃饭!...");
}

}

三、类的使用

类的使用,就是定义成员变量和成员方法

格式

类名 对象名 = new 类名();

通过 对象名. 的形式调用类中的指定成员即可

//成员变量

​ 对象名.成员变量

//成员方法

​ 对象名.成员方法(参数列表中各数据类型对应的值…)

示例

需求
使用学生类中的成员.

public class  StudentTest{public static void main(String [] args){//1. 创建学生类的对象.Student s = new Student();//2. 访问成员变量.System.out.println(s.name);System.out.println(s.age);//3. 给成员变量赋值.s.name = "张三";s.age = 23;//4. 访问成员变量.System.out.println(s.name);System.out.println(s.age);//5. 访问成员方法. s.study();s.eat();       }
}

四、手机类的定义和使用

4,1 需求

定义手机类Phone
属性: 品牌(brand), 价格(price), 颜色(color)
行为: 打电话(call), 发短信(sendMessage)
创建测试类PhoneTest, 在类中定义main方法, 并访问手机类(Phone类)中的成员

public class Phone{String brand;int price;String color;public void call(String name){System.out.println("给"+name+"打电话>>");}public void sendMessage(String name){System.out.println("给"+name+"发短信>>");}}public  class PhoneTest{public static void main(String[] args){Phone p =new Phone();p.name = "华为";p.color = "绿色";System.out,println(p.brand);System.out,println(p.color);        System.out,println(p.price);        //调用方法p.call("峰哥");p.sendMessage(("峰哥");}
}

四、成员变量和局部变量的区别
4.1、简述
成员变量: 指的是定义在类中, 方法外的变量
局部变量: 指的是定义在方法中, 或者方法声明上的变量
它们的区别如下:
定义位置不同
成员变量: 定义在类中, 方法外
局部变量: 定义在方法中, 或者方法声明上
在内存中的存储位置不同
成员变量: 存储在堆内存
局部变量: 存储在栈内存
生命周期不同
成员变量: 随着对象的创建而存在, 随着对象的消失而消失
局部变量: 随着方法的调用而存在, 随着方法的调用完毕而消失
初始化值不同
成员变量: 有默认值
局部变量: 没有默认值, 必须先定义, 再赋值, 然后才能使用

四、封装

通过private关键字,可以防止恶意非法值。

通过private修饰的关键字只能在本类中使用

在开发中一般情况下,成员变量基本上都是用private关键字来修饰的

如果明确知道类或只能怪的某些内容不想让外界访问,都可以通过private来修饰

//学生类
public class Student{//属性String name;       //姓名private int age;    //年龄//getXxx()和setXxx()方法public void setAge(int a) {if(a >= 0 && age <= 150) {//年龄合法, 就赋值.age = a;}}public int getAge() {return age;}//行为public void show() {//被private修饰的内容, 可以在本类中直接访问.System.out.println(name + "..." + age);}
}//学生类的测试类
public class StudentTest{public static void main(String[] args) {//1. 创建学生类的对象Student s = new Student();//2. 给成员变量赋值.s.name = "张三";//s.age = -23;      //被private修饰的内容, 外界无法直接访问.s.setAge(-23);//3. 调用成员方法.s.show();}
}

4.1标准代码

在实际开发中,一般情况下都会加上private,然后提供对饮的getXxx()和setXxx()方法,方便用户访问对应的成员变量.

需求
定义一个标准的学生类Student, 属性: 姓名和年龄, 行为: 学习, 吃饭。
在测试类中创建学生类的对象, 然后访问类中的成员。

public class Student {//属性, 全部用private修饰.//姓名private String name;//年龄private int age;public String getName() {return name;}public void setName(String n) {name = n;}public int getAge() {return age;}public void setAge(int a) {age = a;}//行为, 也就是成员方法.public void study() {System.out.println("键盘敲烂, 月薪过万!");}public void eat() {System.out.println("学习饿了就要吃饭!.");}
}//测试类
public class StudentTest {public static void main(String[] args) {//1. 创建学生对象.Student s = new Student();//2. 设置成员变量值.s.setName("张三");s.setAge(23);//3. 打印成员变量值.System.out.println(s.getName() + "..." + s.getAge());//4. 调用成员方法.s.study();s.eat();}
}

4.2 封装的概述和好处

概述

封装是面向对象编程思想的三大特征之一, 所谓的封装指的就是隐藏对象的属性和实现细节, 仅对外提供一个公共的访问方式.
记忆:
面向对象的三大特征: 封装, 继承, 多态.
问题一: 怎么隐藏?
通过private关键字实现.
问题二: 公共的访问方式是什么?
getXxx() 和 setXxx()方法.

4.2.1、原则
把不需要对外提供的内容都隐藏起来.
把属性隐藏, 并提供公共方法对其访问.
解释: 就是成员变量都用private修饰, 并提供对应的getXxx()和setXxx()方法, 除此以外, 都用public修饰.

4.3、好处

提高代码的安全性.
这点是由private关键字来保证的.
提高代码的复用性.
这点是由方法来保证的, 方法也是封装的一种体现形式.

4.4、this关键字

4.1、概述
this代表本类当前对象的引用, 大白话翻译: 谁调用, this就代表谁
4.2、作用
用来解决局部变量和成员变量重名问题的

4.3、示例
需求
定义一个标准的学生类Student, 属性: 姓名和年龄, 行为: 学习, 吃饭.
在测试类中创建学生类的对象, 然后访问类中的成员.

private String name;//年龄private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;//s.age = 23;}//行为, 也就是成员方法.public void study() {System.out.println("键盘敲烂, 月薪过万!");}public void eat() {System.out.println("学习饿了就要吃饭!.");}
}public class Student {//属性, 全部用private修饰.//姓名private String name;//年龄private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;//s.age = 23;}//行为, 也就是成员方法.public void study() {System.out.println("键盘敲烂, 月薪过万!");}public void eat() {System.out.println("学习饿了就要吃饭!.");}
}//测试类
public class StudentTest {public static void main(String[] args) {//1. 创建学生对象.Student s = new Student();//2. 设置成员变量值.s.setName("张三");s.setAge(23);//3. 打印成员变量值.System.out.println(s.getName() + "..." + s.getAge());//4. 调用成员方法.s.study();s.eat();}
}

五、构造方法

5.1、概述

构造方法是用来创建对象的, 捎带着可以给对象的各个成员变量赋值
大白话: 构造方法就是用来快速对对象的各个属性赋值的

5.2、格式

构造方法名必须和类名完全一致(包括大小写)
构造方法没有返回值类型, 连void都不能写
构造方法没有具体的返回值, 但是可以写return(实际开发, 一般不写)
public 类名(参数类型 参数名1, 参数类型 参数名2) { //这里可以写多个参数.
//给对象的各个属性赋值即可.
}

5.3、示例: 构造方法入门

需求
定义学生类Student, 在类的空参构造中打印一句话"这是构造方法"
在StudentTest测试类中, 创建学生类的对象, 并观察程序的运行结果
小技巧: 创建对象的格式如下:
类名 对象名 = new 构造方法(参数列表);
参考代码


//学生类.
public class Student{//类的空参构造.public Student() {System.out.println("这是构造方法");}
}//学生类的测试类
public class StudentTest{public static void main(String[] args) {Student s = new Student();}
}

5.4、构造方法的注意事项
如果我们没有给出构造方法, 系统将给出一个默认的无参构造供我们使用
如果我们给出了构造方法, 系统将不再提供默认的构造方法给我们使用
这个时候, 如果我们还想使用无参构造, 就必须自己提供
建议定义类时, 我们给出无参构造, 方便用户调用(实际开发都这么做的)
思考题
问: 给成员变量赋值有几种方式?
答: 1. 通过setXxx()方法实现(该方式不会创建新对象)
2. 通过构造方法实现(该方式会创建新对象)

6、标准的类的定义和使用
6.1、格式
以后在实际开发中, 也都是这样写的, 即: 标准的类的定义格式如下:
public class 类名{
//属性(成员变量), 全部用private修饰.

//构造方法, 一般提供两个(无参, 全参)//getXxx()和setXxx()方法//行为(成员方法), 根据需求来定义.

}

6.2、示例
需求
定义一个标准的学生类Student, 属性: 姓名和年龄, 行为: 学习, 吃饭.
在测试类中创建学生类的对象, 然后访问类中的成员.
参考代码
//学生类
public class Student {
//属性(成员变量), 全部用private修饰.
private String name; //姓名
private int age; //年龄

//构造方法, 一般提供两个(无参, 全参)
public Student() {
}
public Student(String name, int age) {this.name = name;this.age = age;
}
//getXxx()和setXxx()方法
public String getName() {return name;
}public void setName(String name) {this.name = name;
}public int getAge() {return age;
}
public void setAge(int age) {this.age = age;
}//行为(成员方法), 根据需求来定义.
public void study() {System.out.println("键盘敲烂, 月薪过万!");
}public void eat() {System.out.println("学习饿了要吃饭");
}
}//学生类的测试类
public class StudentTest {public static void main(String[] args) {//1. 创建学生对象.Student s = new Student();//2. 设置成员变量值.s.setName("张三");s.setAge(23);//3. 打印成员变量值.System.out.println(s.getName() + "..." + s.getAge());//4. 调用成员方法.s.study();s.eat();}
}

六 继承

概念

多个类中存在相同属性和行为时, 将这些内容抽取到单独的一个类中, 那么这多个类就无需再定义这些属性和行为了, 只要继承那个类即可,这个关系就叫继承
注意:
有了继承以后, 我们在定义一个类的时候, 可以在一个已经存在的类的基础上, 还可以定义自己的新成员
⦁ 2、格式
在Java中, 可以通过extends关键字来实现类与类的继承, 具体格式如下:`

public class 类A extends 类B { //子承父业}

解释:
⦁ 类A: 叫子类, 或者派生类.
⦁ 类B: 叫父类, 基类, 或者超类.
我们一般会念做: 子类和父类.

继承例题1

写一个person类,类中有姓名和age,学生和老师类继承它,学生和老师有自己的方法,在学生类中定义study()方法并在老师类中定义teach()方法,调用成员输出.,…

package com.itheima.extents;
//person类
package com.itheima.extents;import javax.xml.soap.SAAJResult;public class Person {String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
//教师类
package com.itheima.extents;public class Teacher extends  Person{public void teach(){System.out.println(name+"在讲课");}
}
//学生类
package com.itheima.extents;public class Student extends  Person{public void Study(){System.out.println(name+"在听课");}
}
//测试类
public class PersonTest {public static void main(String[] args) {Teacher teacher = new Teacher();teacher.name="王凯顺";teacher.age=22;teacher.teach();System.out.println(teacher.getAge());Student student = new Student();        student.name= "提亚娜";student.setAge(23);System.out.println(student.getAge());student.Study();}
}

在以上的例题中,学生和老师的姓名和年龄都是重复定义的,利用继承可以达到复用

继承的优劣

优点

​ 提高了代码的复用性
​ 提高了代码的可维护性
​ 让类与类之间产生关系, 是多态的前提
弊端
​ 让类与类之间产生了关系, 也就让类的耦合性增强了
​ 解释:
​ 开发原则: 高内聚, 低耦合.
​ 内聚: 指的是类自己独立完成某些事情的能力
​ 耦合: 指的是类与类之间的关系

例题2

定义GrandFather类, 该类有一个grandFatherSay()方法, 该方法打印一句话爷爷都是从孙子过来的.
⦁ 定义Father类, 该类有一个fatherSay()方法, 该方法打印一句话爸爸都是从儿子过来的.
⦁ 定义Son类, 分别先继承自GrandFather类和Father类, 此时发现, 上述的两个方法只能同时调用一个.
⦁ 如果想让Son类的对象, 同时能调用上述的两个方法, 则可以这样做:
⦁ Son类继承自Father类, Father类继承自GrandFather类.

//爷爷类
//一个类如果没有显式的写父类, 默认就继承自Object类
//Object类, 是所有类的父类
public class GrandFather {public void grandFather() {System.out.println("grandFather....");}
}
//父亲类
public class Father extends GrandFather{public void father() {System.out.println("father....");}
}
//儿子类
public class Son extends Father {}
//测试类
public class SonTest {public static void main(String[] args) {//创建子类对象.Son s = new Son();//问: Son的对象, 可以调用哪些方法?s.father();         //从Father类继承过来的.s.grandFather();    //从Father类继承过来的, 而Father类又从GrandFather类继承过来了}
}

继承中成员变量访问特点

只能单继承不能多继承—但是可以多层继承

Java中使用变量遵循就近原则, 局部位置有就使用, 没有就去本类的成员位置找. 有就使用, 没有就去父类的成员位置找, 有就使用, 没有就报错

注意: 不考虑父类的父类这种情况, 因为会一直往上找, 直到把所有的父类都找完, 还找不到, 就报错了

调用成员方法时, 也遵循就近原则, 本类中有, 就直接调用, 本类中没有, 就去父类中查找, 有就使用, 没有就报错.

super关键字

概述

代码中默认自带,且super只能写在第一行

super的用法和this很像:
this: 代表本类对象的引用.
super: 代表当前对象的父类的内存空间标识.
解释: 可以理解为父类对象引用.

用法

功能 本类 父类
访问成员变量 this.成员变量名 super.成员变量名
访问构造方法 this(…) super(…)
访问成员方法 this.成员方法名(参数值…) super.成员方法名(参数值…)

七、继承中构造方法的特点

任务:知道每一次都会调用父类的空参.

定义父类Father, 并在空参构造中打印一句话: Father空参构造
定义子类Son, 并在空参构造中打印一句话: Son空参构造
在FatherTest测试类的main方法中, 创建Son类的对象, 并查看程序的执行结果
分别修改Father类和Son类的代码, 添加带参构造, 并观察程序的执行结果

//father类
package com.itheima.extents_03;//父亲类
public class Father  extends GrandFather {public Father() {System.out.println("Father空参构造2 ");}public Father(String name) {System.out.println("Father有参构造2 ");}
}//son类
package com.itheima.extents_03;//儿子类
public class Son extends Father {public Son(String name) {System.out.println("son有参构造1 ");}public Son() {System.out.println("son空参构造1 ");}}//测试类
package com.itheima.extents_03;public class Test {public static void main(String[] args) {Son son = new Son("张三");Son son1 = new Son();}
}

对构造方法的总结

​ 子类中所有的构造方法默认都会访问父类的空参构造
​ 问: 为什么这样设计呢?
​ 答: 用于子类对象访问父类数据前, 对父类数据进行初始化
​ 即: 每一个构造方法的第一条语句默认都是: super()
​ 如果父类没有空参构造, 我们可以通过super(参数)的形式访问父类的带参构造
​ 解释: 但是这样做比较繁琐, 所以建议我们定义类时, 永远手动给出空参构造

八、继承中成员方法的特点

用成员方法时, 也遵循就近原则, 本类中有, 就直接调用, 本类中没有, 就去父类中查找, 有就使用, 没有就报错.

示例

定义Father类, 并在类中定义method()方法和show()方法.
定义Son类, 并在类中定义method()方法和show()方法.
在FatherTest测试类中, 创建Son类的对象, 并调用类中的成员方法.
注释子类中的method()方法或者show()方法, 并观察程序的执行结果.

//父类
public class Father {public void show() {System.out.println("Father show...");}public void method() {System.out.println("Father method...");}
}//子类
public class Son extends Father{public void show() {System.out.println("Son show...");}public void method() {System.out.println("Son method...");}
}//案例: 演示继承关系中的 成员方法的特点.
/*结论: 记忆继承关系中, 调用成员方法时, 也遵循"就近原则", 本类中有, 就直接调用,本类中没有, 就去父类查找, 有就调用, 没有就报错.*/
public class FatherTest {public static void main(String[] args) {//1. 创建Son类对象.Son s = new Son();//2. 调用Son类中的方法.s.method();s.show();}
}

九、方法重写

9.1、概述
子类中出现和父类一模一样的方法时, 称为方法重写. 方法重写要求返回值的数据类型也必须一样.
9.2、应用场景
当子类需要使用父类的功能, 而功能主体又有自己独有需求的时候, 就可以考虑重写父类中的方法了, 这样, 即沿袭了父类的功能, 又定义了子类特有的内容.
9.3、示例
需求
定义Phone类, 并在类中定义call(String name)方法.
定义NewPhone类, 继承Phone类, 然后重写call(String name)方法.
在PhoneTest测试类中, 分别创建两个类的对象, 然后调用call()方法, 观察程序执行结果.
参考代码

//定义一个手机类.
public class Phone {//打电话的功能.public void call(String name) {System.out.println("给" + name + "打电话!...");}
}//定义一个手机类, 表示: 新式手机.
public class NewPhone extends Phone{//重写父类Phone#call()方法, 在打电话的时候, 播放彩铃.@Overridepublic void call(String name) {//因为基本的打电话的功能, 父类已经实现了, 我们可以直接拿来用.//System.out.println("给" + name + "打电话!...");//调用父类的call()方法, 实现打电话功能.super.call(name);//在父类call()方法的功能主体上, 加入自己独有的需求: 播放彩铃System.out.println("播放彩铃...");}
}//案例: 演示方法重写
/*方法重写:概述:子类出现和父类一模一样的方法时, 称为方法重写.方法重写要求返回值的数据类型也必须一致.注意事项:1. 子类重写父类方法时, 要用 @Override注解 来修饰.2. 父类中私有的方法不能被子类重写.3. 子类重写父类方法时, 访问权限不能更低.private < 默认 < protected < public*/
public class PhoneTest {public static void main(String[] args) {//1. 测试 老式手机.Phone p = new Phone();p.call("刘亦菲");System.out.println("----------------");//2. 测试 新式手机NewPhone np = new NewPhone();np.call("赵丽颖");}
}

子类重写父类方法时, 方法声明上要用@Override注解来修饰.
父类中私有的方法不能被重写.
子类重写父类方法时, 访问权限不能更低

老师和学生案例(继承版)

注意: 子类继承父类时, 一般构造方法也要手动生成, 目的是为了帮助我们快速创建对象并赋值.

10 老师和学生案例(继承版)
10.1、需求
已知老师类Teacher, 属性有姓名和年龄, 行为有teach().
已知学生类Student, 属性有姓名和年龄, 行为有study().
分析上述的需求, 并通过代码实现.
在PersonTest类的main方法中, 分别创建老师类和学生类的对象, 然后访问其成员.
10.2、参考代码
代码:

//父类, 里边定义的是整个继承体系的: 共性内容.
public class Person {//属性.private String name;private int age;//构造方法.
public Person() {
}
public Person(String name, int age) {this.name = name;this.age = age;
}
//getXxx(), setXxx()public String getName() {return name;
}public void setName(String name) {this.name = name;
}public int getAge() {return age;
}public void setAge(int age) {this.age = age;
}//行为.
public void eat() {System.out.println("人要吃饭!");
}
}//老师类
public class Teacher extends Person{//属性.//构造方法, 子类的空参访问父类的空参, 子类的全参访问父类的全参.public Teacher() {super();}public Teacher(String name, int age) {super(name, age);
}//getXxx(), setXxx(), 从父类继承.//行为, 这里可以定义本类独有的行为.
//重写父类的eat()方法
@Override
public void eat() {System.out.println("老师喝牛肉汤!...");
}//加入老师类独有的功能
public void teach() {System.out.println("老师要激情高涨的讲课, 帮助学员实现高薪就业!...");
}
}//学生类
public class Student extends Person{//属性.//构造方法, 子类的空参访问父类的空参, 子类的全参访问父类的全参.public Student() {super();}public Student(String name, int age) {super(name, age);
}//getXxx(), setXxx(), 从父类继承.//行为, 这里可以定义本类独有的行为.
//重写父类的eat()方法
@Override
public void eat() {System.out.println("学生吃牛肉!...");
}//加入老师类独有的功能
public void study() {System.out.println("键盘敲烂, 月薪过万!...");
}
}//测试类: 演示老师和学生案例(继承版)
public class PersonTest {public static void main(String[] args) {//1. 测试老师类, 空参构造.//1.1 创建对象.Teacher t1 = new Teacher();//1.2 给属性赋值.t1.setName("刘亦菲");t1.setAge(33);//1.3 打印属性值.System.out.println(t1.getName() + "..." + t1.getAge());//1.4 调用方法t1.eat();t1.teach();System.out.println("-----------------------------");//2. 测试老师类, 全参构造.//2.1 创建对象, 并给属性赋值.Teacher t2 = new Teacher("赵丽颖", 31);//2.2 打印属性值.System.out.println(t2.getName() + "..." + t2.getAge());//2.3 调用方法t2.eat();t2.teach();System.out.println("-----------------------------");//3. 测试学生类, 空参构造, 留给你自己写.//4. 测试学生类, 全参构造, 留给你自己写.
}     }

注意: 子类继承父类时, 一般构造方法也要手动生成, 目的是为了帮助我们快速创建对象并赋值.

十 多态

1、概述

多态指的是同一个事物(或者对象)在不同时刻表现出来的不同状态.
例如: 一杯水.
常温下是液体.
高温下是气体.
低温下是固体.
但是水还是那杯水, 只不过在不同的环境下, 表现出来的状态不同.

2、前提条件

要有继承关系
要有方法重写
要有父类引用指向子类对象

3、示例: 多态入门

例题1

定义动物类Animal, 并在类中定义一个成员方法: eat()
定义猫类Cat, 继承Animal类, 并重写eat()方法.
在AnimalTest测试类的main方法中, 通过多态的方式创建猫类对象.
通过猫类对象, 调用eat()方法.
参考代码

//父类, 动物类
public class Animal {public void eat() {System.out.println("动物要吃!...");}
}//子类: 猫类
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}
}//案例: 演示多态入门.
/*多态:概述:同一个事物在不同时刻表现出来的不同状态, 形态.前提条件:1. 要有继承关系.2. 要有方法重写.3. 要有父类引用指向子类对象.*/
public class AnimalTest {public static void main(String[] args) {//1. 通过多态的形式创建动物类对象.Animal an = new Cat();//2. 调用该对象的eat()方法.an.eat();    //猫吃鱼.}
}

2多态中的成员访问特点

成员变量: 编译看左边, 运行看左边.
成员方法: 编译看左边, 运行看右边.

例题2

定义一个人类Person. 属性为姓名和年龄, 行为是: eat()方法.
定义Student类, 继承自Person类, 定义age属性及重写eat()方法.
在PersonTest测试类的main方法中, 创建Student类的对象, 并打印其成员.

//父类, 表示人类.
public class Person {//属性String name = "刘亦菲";int age = 50;//行为public void eat() {System.out.println("人要吃饭!");}
}//子类, 学生类
public class Student extends Person{int age = 30;@Overridepublic void eat() {System.out.println("学生吃牛肉!");}
}//案例: 演示多态中的成员访问特点.
/*结论: 记忆1. 成员变量: 编译看左, 运行看左.编译的时候, 看左边的数据类型有没有这个变量, 有不报错, 没有就报错.运行的时候, 具体运行的是左边的数据类型里边的: 此变量.2. 成员方法: 编译看左, 运行看右.编译的时候, 看左边的数据类型有没有这个方法, 有不报错, 没有就报错.运行的时候, 具体运行的是右边的数据类型里边的: 此方法.原因是因为: 方法有重写, 而变量没有.*/public class PersonTest {public static void main(String[] args) {//1. 通过多态, 创建学生类对象.Person p = new Student();//2. 调用成员变量.System.out.println(p.age);      //50//3. 调用成员方法.p.eat();                        //1学生吃牛肉}
}

好处和弊端.

好处

提高了程序的扩展性.

弊端

父类引用不能访问子类的特有功能.
问: 那如何解决这个问题呢?
答: 通过向下转型来解决这个问题

例题3

定义动物类Animal, 该类有一个eat()方法.
定义猫类Cat, 继承自Animal类, 该类有一个自己独有的方法: catchMouse().
在AnimalTest测试类中, 通过多态的方式创建Cat类的对象, 并尝试调用catchMouse()方法.
参考代码

//父类, 动物类
public class Animal {public void eat() {System.out.println("动物要吃");}
}//子类, 猫类
public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼!");}public void catchMouse() {System.out.println("猫会抓老鼠!....");}
}//动物类案例测试类.
/*多态的好处:提高了代码的扩展性.多态的弊端:父类引用不能直接使用子类的特有成员.如何解决上述的问题?通过向下转型解决,即: 多态形式的创建对象的操作 -> 转变成 普通的创建对象的操作. .*/
public class AnimalTest {public static void main(String[] args) {//1 多态形式的创建猫类对象Animal an = new Cat();//2. 演示多态的弊端.an.eat();               //编译看左 运行看右.//3. 升级功能: 尝试通过多态版的 猫类对象, 调用猫类中独有的 catchMouse()功能.//an.catchMouse();      //这样做不行, 因为an是Animal动物类的引用, 我们不能说  动物会抓老鼠//4. 通过向下转型, 把 多态版的 猫类对象 ->  Cat类型的猫类对象.Cat c = (Cat)an;          //引用类型的: 向下转型,     即: 大 -> 小.c.catchMouse();//int a = (int)10.3;        基本类型的: 强制类型转换, 即: 大 -> 小.}
}

强制转换不能转换其他的

比如说 是Cat类只能转Cat类 不能转Dog 类

向上转型和向下转型

向上转型

//格式
父类型 对象名 = new 子类型();

//例如
Animal an = new Cat();

向下转型

//格式
子类型 对象名 = (子类型)父类引用;

//例如
Cat c = (Cat)an;
小Bug
//下述代码会报: ClassCastException(类型转换异常)
Animal an = new Cat();
Cat c = (Cat)an; //这样写不报错.
Dog d = (Dog)an; //这样写会报错.

例题4

示例: 猫狗案例
需求
已知猫狗都有姓名和年龄, 都要吃饭.
猫类独有自己的catchMouse()方法, 狗类独有自己的lookHome()方法.
在AnimalTest测试类的main方法中, 通过多态分别创建猫类, 狗类的对象.
分别通过猫类对象和狗类对象, 访问对象的成员.

//父类, 动物类
public class Animal {//属性, 姓名, 年龄private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//行为, 吃饭public void eat() {System.out.println("动物要吃饭!");}
}//子类: 猫类
public class Cat extends Animal{//构造方法public Cat() {}public Cat(String name, int age) {super(name, age);}//成员方法//重写Animal#eat()@Overridepublic void eat() {System.out.println("猫吃鱼");}//定义自己独有的行为public void catchMouse() {System.out.println("猫会抓老鼠");}
}//子类: 狗类
public class Dog extends Animal{//构造方法public Dog() {}public Dog(String name, int age) {super(name, age);}//成员方法//重写Animal#eat()@Overridepublic void eat() {System.out.println("狗吃肉");}//定义自己独有的行为public void lookHome() {System.out.println("狗会看家!");}
}//扩展: instanceof 关键字.
/*instanceof 关键字格式:引用(对象)   instanceof   数据类型作用:用来判断前边的引用(或者是对象) 是否是 后边的数据类型.例如:Cat c = new Cat();c instanceof Cat        ->  truec instanceof Dog        ->  false*/
public class AnimalTest {public static void main(String[] args) {//需求: 定义一个show()方法, 接收任意的动物类对象, 然后调用该对象的eat()方法.//扩展功能: 如果是猫, 就抓老鼠, 如果是狗, 就看家.Cat c = new Cat();show(c);            //猫吃鱼.System.out.println("-------------------");//调用Dog#eat()Dog d = new Dog();show(d);          //狗吃肉}//方式二: 多态版public static void show(Animal an) {        //Animal an = new Dog();  根据多态访问成员方法的规则: 编译看左, 运行看右.an.eat();//判断传入的是否是猫类if (an instanceof Cat) {//走到这里, 说明是猫类对象, 向下转型, 然后调用方法即可.Cat c = (Cat)an;c.catchMouse();} else if(an instanceof Dog) {//走到这里, 说明是狗类对象, 向下转型, 然后调用方法即可.Dog d = (Dog)an;d.lookHome();}}}

大数据笔记8—java基础篇4(面向对象-封装-继承-多态)相关推荐

  1. 大数据笔记10—java基础篇6(集合1-Collection)

    集合 集合(Collection) 一.迭代器<iterator> 案例一 二.并发修改异常 三.Collection集合 案例一(Collection练习) 案例二(Collection ...

  2. 大数据笔记9—java基础篇5(API)

    java_API API String类 创建字符串对象的区别对比 String字符串的特点 字符串的比较 例题(String) 例题1. 模拟登陆 例题2遍历字符串 例题3.案例 :统计字符次数 例 ...

  3. 大数据笔记16—java基础篇12(JDBC 、连接池、事务)

    目录 JDBC jdbc概述 jdbc入门案例 API详解 jdbc工具类 预编译执行平台 1.SQL注入问题(安全问题) 2API详解:预处理对象(PreparedStatement) 使用连接池重 ...

  4. 大数据笔记11—java基础篇7(集合2-Map)

    目录Map Map集合 2.1 Map入门 2.2 Map集合的成员方法 Collections类 斗地主案例 苟有恒,何必三更眠五更起: 最无益,莫过一日曝十日寒. Map集合 概述: Map集合是 ...

  5. 大数据笔记30—Hadoop基础篇13(Hive优化及数据倾斜)

    Hive优化及数据倾斜 知识点01:回顾 知识点02:目标 知识点03:Hive函数:多行转多列 知识点04:Hive函数:多行转单列 知识点05:Hive函数:多列转多行 知识点06:Hive函数: ...

  6. 菜鸟学习笔记:Java基础篇7(包装类、时间相关类、文件类、异常处理类)

    菜鸟学习笔记:Java其他常用类 基本数据类型包装类 时间处理和文件处理相关类 Date时间类 SimpleDateFormat Calendar日历类 文件类 异常机制 异常的概念 Java异常处理 ...

  7. 菜鸟学习笔记:Java基础篇6(数组、字符串)

    菜鸟学习笔记:Java常用类(数组.字符串) 数组 概述 数组的定义 二维数组 数组查找和排序 查找 排序 数组运用--字符串 不可变字符序列(String) 可变字符序列(StringBuilder ...

  8. 菜鸟学习笔记:Java基础篇4(面向对象三大特征)

    菜鸟学习笔记:Java面向对象篇中 继承 概念 方法重写(override) Object类 Super关键字 组合 final关键字补充 封装 访问控制符 多态 继承 概念 继续上一篇的例子: #m ...

  9. 菜鸟学习笔记:Java基础篇3(面向对象思想、程序执行过程内存分析、面向对象重要概念)

    菜鸟学习笔记:Java面向对象篇上 Java面向对象的思想 Java程序执行过程内存分析 Java垃圾回收机制 构造方法 方法重载(overload) static关键字 this关键字 Java面向 ...

最新文章

  1. 交叉编译inetutils并配置telnet服务
  2. html修改上传文件名,input(file)样式修改及上传文件名显示
  3. 1.物理系统PhysicsWorld,RayCast
  4. c++项目源码_C/C++学习日记:用C++制作餐饮管理系统(附源码),可以用来做毕设的项目!...
  5. 质数和分解(动态规划)
  6. DataMan-美团旅行数据质量监管平台实践
  7. php 情书,php趣味编程 - php输出笛卡尔情书的秘密
  8. 用 Python 编写一个天气查询应用
  9. 使用Kalibr进行IMU+相机的标定
  10. BIND rndc—使用说明
  11. 【C语言】ASCII码表
  12. 软考网络工程师第一章复习
  13. java 格式化日期 星期_java 日期格式化
  14. C/C++求职者必备的20道面试题
  15. 技嘉ide模式怎么改,电脑BIOS中怎么设置硬盘为IDE模式
  16. 赛灵思计算平台ACAP技术细节全揭秘
  17. 案例分享:Qt+Arm+Fpga医疗肾镜(又名内窥镜)(实时影像、冻结、拍照、白平衡、九宫格、录像、背光调整、硬件光源调整、光源手动自动调整、物理按键)
  18. 电脑键盘功能基础知识,快速入门,抓住这份详细教程
  19. 使用jmeter进行压测
  20. 老虎机数字抽奖(可控制结果)

热门文章

  1. 船东提单和货代提单差距这么大?
  2. Java序列化与JNDI注入
  3. 基于网页自动化Selenium IDE的安装与部署 图书馆选座、网站防休眠、自动点击等
  4. python基础(六)函数
  5. 全球及中国果蔬切丁机行业研究及十四五规划分析报告
  6. 自然语言处理(基于预训练模型)01FMM分词算法
  7. 从零开始搭建创业公司后台技术栈
  8. 百度云盘不限速下载工具(附带开源源码)
  9. Hive编程指南中的命令
  10. bt种子自动发布 linux,Linux制作BT种子并获取BT种子信息