首页 > 其他分享 >重学面向对象-基础篇03封装、继承和多态

重学面向对象-基础篇03封装、继承和多态

时间:2024-08-08 11:42:14浏览次数:13  
标签:03 String Person age 多态 sex 面向对象 public name

封装、继承和多态

基础概念

封装:把对象的属性和方法结合城一个独立的整体,隐藏实现细节,并提供对外访问的接口

继承:从已知的一个类中派生出一个新的类,叫子类。子类实现了父类所有非私有化的属性和方法,并根据实际需求扩展出新的行为

多态:多个不同的对象对同一消息作出响应,同一消息根据不同的对象而采用各种不同的方法

代码实现

类的封装

package com.test.entity;

public class Person {
    private String name; //现在类的属性只能被自己直接访问
    private int age;
    private String sex;

    public Person(String name, int age, String sex) { //构造方法也要声明为公共,否则对象都构造不了
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }
}
package com.test;

import com.test.entity.Person;

public class Main {
    public static void main(String[] args) {
        Person person = new Person("小明",18,"男");
        System.out.println(person.getName()); //只能通过调用getName()方法来获取名字
    }
}

类的继承

//定义一父类Person
public class Person{
    String name;
    int age;
    String sex;
}

//工人类
public class Worker extends Person{}

//学生类
public class Student extends Person{}

//class前面添加final关键字表示这个类已经是最终形态,不能继承
public final class Person {}
//父类
public class Person {
    String name;
    int age;
    String sex;

    public void hello(){
        System.out.println("我叫 "+name+",今年 "+age+" 岁了!");
    }
}

//子类
public class Student extends Person{
    public void study(){
        System.out.println("我的名字是 "+name+",我在学习!");   //可以直接访问父类中定义的name属性
    }
}

//实际应用
public static void main(String[] args) {
    Student student = new Student();
    student.study();    //子类不仅有自己的独特技能
    student.hello();    //还继承了父类的全部技能
}
//父类存在有参构造方法,子类必须在构造方法中调用
public class Person {
    protected String name;   //因为子类需要用这些属性,所以说我们就将这些变成protected,外部不允许访问
    protected int age;
    protected String sex;
    protected String profession;

    //构造方法也改成protected,只能子类用
    protected Person(String name, int age, String sex, String profession) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.profession = profession;
    }

    public void hello(){
        System.out.println("["+profession+"] 我叫 "+name+",今年 "+age+" 岁了!");
    }
}

//子类Student
public class Student extends Person{
    public Student(String name, int age, String sex) {    //因为学生职业已经确定,所以说学生直接填写就可以了
        super(name, age, sex, "学生");   //使用super代表父类,父类的构造方法就是super()
    }

    public void study(){
        System.out.println("我的名字是 "+name+",我在学习!");
    }
}

//子类Worker
public class Worker extends Person{
    public Worker(String name, int age, String sex) {
        super(name, age, sex, "工人");    //父类构造调用必须在最前面
        System.out.println("工人构造成功!");    //注意,在调用父类构造方法之前,不允许执行任何代码,只能在之后执行
    }
}

//实际使用
public static void main(String[] args) {
    Person person = new Student("小明", 18, "男"); //使用父类型的变量,去引用一个子类对象(向上转型)
    Student student = (Student) person; //使用强制类型转换(向下转型)
    person.Hello(); //父类对象的引用相当于作为父亲来使用,只能访问父类对象的内容
    student.study();
}

//[学生]我叫小明,今年 18岁了!
//我叫小明,我在学习
//判断变量引用对象是什么类
public static void main(String[] args) {
    Person person = new Student("小明", 18, "男");
    if(person instanceof Student) {   //我们可以使用instanceof关键字来对类型进行判断
        System.out.println("对象是 Student 类型的");
    }
    if(person instanceof Person) {
        System.out.println("对象是 Person 类型的");
    }
}

//子类可以定义和父类同名属性
public class Worker extends Person{
    protected String name;   //子类中同样可以定义name属性

    public Worker(String name, int age, String sex) {
        super(name, age, sex, "工人");
    }

    //在子类中直接使用时
    public void work(){
        System.out.println("我是 "+name+",我在工作!");
        //这里的name,依然是作用域最近的哪一个,也就是在当前子类中定义的name属性,而不是父类的name属性
    }

    //子类存在同名变量,访问父类同名变量
    public void work(){
        System.out.println("我是 "+super.name+",我在工作!");
        //这里使用super.name来表示需要的是父类的name变量
    }
}

注:没有super.super这种用法,也就是说如果存在多级继承的话,那么最多只能通过这种方法访问到父类的属性

顶层Object类

所有类都默认继承自Object类,除非手动指定继承的类型,但是依然改变不了最顶层的父类是Object类。

所有类都包含Object类中的方法所有类都默认继承自Object类,除非手动指定继承的类型,但是依然改变不了最顶层的父类是Object类。所有类都包含Object类中的方法。

public class Person extends Oject{
//除非我们手动指定要继承的类是什么,实际上默认情况下所有的类都是继承自Object的,只是可以省略
}
public void println(Object x) {
    String s = String.valueOf(x); //调用对象的toString方法
    synchronized(this){
        print(s);
        newLine();
    }
}

//默认比较两个对象是否为同一个对象,这里得到的肯定是false
public static void main(String[] args) {
    Person p1 = new Student("小明", 18, "男");
    Person p2 = new Student("小明", 18, "男");
    System.out.println(p1.equals(p2));
}
//实现“如果名字、年龄、性别都完全相同,则肯定是同一个人”,需要修改equals的默认实现

方法的重写

方法的重载是为某个方法提供更多种类,而方法的重写是覆盖原有的方法实现

public class Person{
    @Override //重写方法一般使用@Override注解
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (obj instanceof Person) {
            Person person = (Person) obj;
            return this.name.equals(person.name) && //字符串内容的比较,不能使用==,必须使用equals方法
                this.age == person.age && //基本类型的比较跟之前一样,直接==
                this.sex.equals(person.sex);
        }
        return false;
    }
    
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", sex=" + sex + ", profession=" + profession + "]";
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Student("Ming", 18, "male");
        Person p2 = new Student("Ming", 18, "male");
        System.out.println(p1.equals(p2));
        System.out.println(p1);
    }
}

true
Person [name=Ming, age=18, sex=male, profession=学生]

基于这种方法可以重写的特性,对于一个类定义的行为,不同的子类可以出现不同的行为;不同的子类,对于同一个方法会产生不同的结果

面向对象编程中多态特性的一种体现

public class Person {
    ...
    public void exam() {
        System.out.println("我是考试方法");
    }
}

public class Student {
    ...
    @Override
    public void exam() {
        System.out.println("我是做题蛆,我要拿A");
    }
}

public class Worker {
    ...
    @Override
    public void exam() {
        System.out.println("我是工人,我要拿S");
    }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Student("Ming", 18, "male");
        Person p2 = new Worker("Wang", 20, "male");
        p1.exam();
        p2.exam();
    }
}

如果不希望子类重写某个方法,我们可以在方法前添加final关键字,表示这个方法已经是最终形态

如果父类中方法的可见性为private,那么子类同样无法访问,也就不能重写,但是可以定义同名方法

在重写父类方法时,如果希望调用父类原本的方法实现,那么同样可以使用super关键字

子类在重写父类方法时,不能降低父类方法中的可见性

抽象类由于不是具体的类定义(它是类的抽象)可能会存在某些方法没有实现,因此无法直接通过new关键字来直接创建对象

要使用抽象类,我们只能去创建它的子类对象

具体的实现,需要由子类来完成,而且如果是子类,必须要实现抽象类中所有抽象方法

抽象类由于不是具体的类定义(它是类的抽象)可能会存在某些方法没有实现,因此无法直接通过new关键字来直接创建对象

抽象类一般只用作继承使用,抽象类的子类也可以是一个抽象类

public abstract class Person { //添加abstract关键字,表明此为抽象类
    protected String name; //大体和普通类差不多
    protected int age;
    protected String sex;
    protected String profession;

    protected Person(String name, int age, String sex, String profession) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.profession = profession;
    }

    public abstract void exam();  //抽象类中可以有抽象方法,也就是说这个方法只有定义,没有方法体
}

public class Worker extends Person {

    public Worker(String name, int age, String sex) {
        super(name, age, sex, "工人");
    }

    @Override
    public void exam() { //子类必须要实现抽象类所有的抽象方法,强制要求,否则无法通过编译
        System.out.println("我是工人,做题我不擅长,只能得到D");
    }
}

public class Student extends Person { //如果抽象类的子类也是抽象类,那么可以不用实现父类中的抽象方法
    public Student(String name, int age, String sex) {
        super(name, age, sex, "学生");
    }

    @Override //抽象类中并非只有抽象方法,1抽象类中也能有正常方法的实现
    public void exam() {
        System.out.println("我是学生,我要A");
    }
}

接口只代表某个确切的功能,接口一般只代表某些功能的抽象,接口包含了一些列方法的定义,类可以实现这个接口,表示类支持接口代表的功能

接口的目标就是将类所具有某些的行为抽象出来

//Study.java
public interface Study { //使用interface表示这是一个接口
    void study(); //接口中只能定义访问权限为public抽象方法,其中public和abstract关键字可以省略
}
//Student.java
public class Student extends Person implements Study {
    public Student(String name, int age, String sex) {
        super(name, age, sex, "学生");
    }

    @Override
    public void study() {
        System.out.println("我会学习!");
    }
}

//Teacher.java
public class Teacher extends Person implements Study {
    protected Teacher(String name, int age, String sex) {
        super(name, age, sex, "教师");
    }

    @Override
    public void study() {
        System.out.println("我会加倍学习!");
        ;
    }
}

接口不同于继承,接口可以同时实现多个

public class Student extends Person implements Study, A, B, C {} //多个接口的实现使用逗号隔开

接口跟抽象类一样,不能直接创建对象

我们也可以将接口实现类的对象以接口的形式去使用

当做接口使用时,只有接口中定义的方法和Object类的方法,无法使用类本身的方法和父类的方法

接口同样支持向下转型

从Java8开始,接口中可以存在方法的默认实现(如果方法在接口中存在默认实现,那么实现类中不强制要求进行实现)

接口中不允许存在成员变量和成员方法,但是可以存在静态变量和静态方法

public interface Study {
    public static final int a = 10;   //接口中定义的静态变量只能是public static final的
  
  	public static void test(){    //接口中定义的静态方法也只能是public的
        System.out.println("我是静态方法");
    }
    
    void study();
}

可以直接通过接口名.的方式使用静态内容

接口可以继承自其他接口

接口没有继承数量限制,接口支持多继承

接口的继承相当于是对接口功能的融合

Object类中提供的克隆方法

package java.lang;

public interface Cloneable {    //这个接口中什么都没定义
}

实现接口后,需要将克隆方法可见性提升,不然无法使用

public class Student extends Person implements Study, Cloneable {   //首先实现Cloneable接口,表示这个类具有克隆的功能
    public Student(String name, int age, String sex) {
        super(name, age, sex, "学生");
    }

    @Override
    public Object clone() throws CloneNotSupportedException {   //提升clone方法的访问权限
        return super.clone();   //因为底层是C++实现,我们直接调用父类的实现就可以了
    }

    @Override
    public void study() {
        System.out.println("我会学习!");
    }
}
public static void main(String[] args) throws CloneNotSupportedException {  //这里向上抛出一下异常,还没学异常,所以说照着写就行了
    Student student = new Student("小明", 18, "男");
    Student clone = (Student) student.clone();   //调用clone方法,得到一个克隆的对象
    System.out.println(student);
    System.out.println(clone);
    System.out.println(student == clone);
}

原对象和克隆对象,是两个不同的对象,但是他们的各种属性都是完全一样的,此处的clone方法是浅拷贝

  • 浅拷贝: 对于类中基本数据类型,会直接复制值给拷贝对象;对于引用类型,只会复制对象的地址,而实际上指向的还是原来的那个对象,拷贝个基莫。
  • 深拷贝: 无论是基本类型还是引用类型,深拷贝会将引用类型的所有内容,全部拷贝为一个新的对象,包括对象内部的所有成员变量,也会进行拷贝。

标签:03,String,Person,age,多态,sex,面向对象,public,name
From: https://www.cnblogs.com/microwang/p/18348613

相关文章

  • Java基础(面向对象)
    标签(空格分隔):Java面向对象的特征一:封装与隐藏一、问题引入当我们创建一个类的对象以后,我们可以通过“对象.属性”的方法,对对象的属性进行赋值。这里,赋值操作要受到属性的数据类型和储存范围的制约。除此之外,没有其他约束条件。但是,实际问题中,我们往往需要给属性赋值加入额外......
  • 基于STM32F103的FreeRTOS系列(七)·任务创建·列表的使用超详细解析
    目录1. 列表和列表项1.1 列表和列表项简介1.1.1  列表1.1.2  列表项1.1.3  迷你列表项1.1.4 列表与列表项关系图1.2 列表初始化1.3 列表项的初始化1.4 列表项的插入函数1.5 列表项的末尾插入1.6 列表项的删除1.7 列表的遍历1. 列表......
  • 034.CI4框架CodeIgniter,纯净windows系统,一步步安装composer和CodeIgniter 4.5.4
    安装git选择路径 一路回车安装 安装phpstudy 安装好的界面 下载php8.2.9  点一下默认配置,确定 php版本要选择php8.2.9 需要安装的php扩展如下 点开网站的管理,设置一个根目录 php,启动 在根目录创建一个index.html的文件,用浏览器打开,看看能不能访......
  • 面向对象程序设计(C++)之 String 类
    1.String构造函数String可以理解为一个字符数组,在创建String类型变量的时候可以使用很多形式,因为String有很多实用的构造函数首先使用String类要包含头文件#include<string>接下来使用代码依次演示上述构造函数的用法: #include<iostream>#include<string>......
  • D40 2-SAT POJ3683 Priest John's Busiest Day
    视频链接:D402-SATPOJ3683PriestJohn'sBusiestDay_哔哩哔哩_bilibili   POJ3683--PriestJohn'sBusiestDay(poj.org)#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>usingnamespacestd;......
  • Java 基础 (面向对象高级 一)
    static static-static修饰成员变量static叫静态,可以修饰成员变量、成员方法。成员变量按照有无static修饰,分为两种:类变量:有static修饰,属于类在计算机里只有一份,会被类的全部对象共享。实例变量(对象的变量):无static修饰,属于每个对象的。 static-类变量应用场景 在开......
  • SSM+MySQL四川工商学院图书馆管理系统-计算机毕设 附源码 03457
    SSM四川工商学院图书馆管理系统目 录摘 要1绪论1.1课题背景1.2研究目的和意义1.3国内外研究现状1.4系统设计思想1.5本章小结2 开发环境及相关技术介绍2.1MySQL数据库的介绍2.2 B/S架构的介绍2.3 Java语言2.4 SSM框架2.5本章小结3 ......
  • 我在一台设备上遇到“SMPTHeloError: (501, b'语法无效的 HELO 参数')”,但在其他设备
    我正在制作一个程序,该程序应该定期向我发送电子邮件,以便我可以对工作设备进行定期状态检查。我需要使用该程序的计算机在行SMPTHeloError:(501,b'SyntacticallyinvalidHELOargument(s)')处给了我错误server.login(from_address,password)当我在我的个......
  • Java SE核心技术——11多态
    多态的概念多态是指一个变量在不同的环境中有不同的体现,是面向对象特征之一多态就是同一个接口,使用不同的实例而执行不同的操作多态是对象多种表现形式的体现:同一时间发生在不同对象上会产生不同的结果。多态的优点消除类型之间的耦合关系可替换性可扩充性接口性灵活......
  • Dreamforce '24重磅来袭!年度盛会将有何惊喜?
     作为Salesforce的旗舰会议,Dreamforce的历史已有20余年之久,是生态系统中的年度亮点。现如今,Dreamforce已经适应了线上受众的需求,通过Salesforce+提供直播和点播的参与方式。 近期,Salesforce宣布Dreamforce'24将于9月17日-19日举行,一年一度的科技盛会又要开始 Dreamforce......