Java的封装与继承

封装继承

访问修饰符

  • public,对外公开
  • protected,对子类和同一个包中的类公开
  • 默认级别
  • private,只有本身可以访问

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7yNwxPSX-1631068658025)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4b5d501c-76ef-4870-a3c6-226776ca2588/Untitled.png)]

访问修饰符的细节

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tzMFlozE-1631068658029)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/24f97179-0d6e-4bdb-82d3-653ea99c9cdc/Untitled.png)]

  • 修饰符可以用来修饰类中的属性,成员方法以及类
  • 只有默认的和public才可以修饰类,并且遵循上述访问权限的特点
  • 成员方法的访问规则和属性完全一样

封装

封装就是把抽象出来的数据[属性]和对数据操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法]才能对数据进行操作(对电视机的操作就是典型封装)

可以隐藏实现细节:方法(连接数据库)< - -调用(传入参数)

可以对数据进行验证,保证安全合理

封装实现的步骤

  • 将属性私有化(不能直接修改属性)
  • 提供一个公告的set方法,用于对数学判断并赋值(可以假如数据验证的业务逻辑)
public void set(类型 参数名)
{
		属性=参数名
}
  • 提供一个公共的get方法,用于获取属性的值
public 数据类型 get()
{
		return xx;
}

封装的简单例子

目的:不能随便查看人的年龄,工资等隐私,年龄要合理设置,name的长度在2~6之间

package com.hh.encap;

public class Encapsulation01 {

    public static void main(String[] args) {
        Person person=new Person();
        person.setName("jack8888");
        person.setAge(38);
        person.setSalary(30000);
        System.out.println(person.info());

    }
}
class Person{
    public String name;
    private int age;
    private double salary;
    //使用快捷键生成,更快

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length() >= 2 && name.length() <= 6) {
            this.name = name;
        }
        else {
            System.out.println("你的名字长度不符合要求,需要在2~6,默认姓名为第一书记");
            this.name="第一书记";
        }
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 1 && age <= 120) {
            this.age = age;
        }
        else{
            System.out.println("你设置的年龄不对,需要在1-120以内,给一个默认年龄为18");
            this.age=18;//给默认年龄
        }
    }
    public double getSalary() {
        //可以在这里增加判断或者限定
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //写一个方法返回
    public String info()
    {
        return "信息为name= "+name+" age= "+age+" 薪水 "+salary;
    }
}

封装与构造器的配合使用

package com.hh.encap;

public class Encapsulation01 {

    public static void main(String[] args) {
        Person person=new Person();
        person.setName("jack8888");
        person.setAge(38);
        person.setSalary(30000);
        System.out.println(person.info());
        Person smith=new Person("smith",300,1200);
        System.out.println("=============\n"+smith.info());
    }
}
class Person{
    public String name;
    private int age;
    private double salary;
    
     public  Person()
      {

     }
     //三个属性的构造器
    public Person(String name, int age, double salary) {

        //可以将set方法下载构造器,仍然可以验证
        setName(name);
        setAge(age);
        setSalary(salary);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length() >= 2 && name.length() <= 6) {
            this.name = name;
        }
        else {
            System.out.println("你的名字长度不符合要求,需要在2~6,默认姓名为第一书记");
            this.name="第一书记";
        }
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 1 && age <= 120) {
            this.age = age;
        }
        else{
            System.out.println("你设置的年龄不对,需要在1-120以内,给一个默认年龄为18");
            this.age=18;//给默认年龄
        }
    }
    public double getSalary() {
        //可以在这里增加判断或者限定
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //写一个方法返回
    public String info()
    {
        return "信息为name= "+name+" age= "+age+" 薪水 "+salary;
    }
}

简单练习

在AccountTest类中进行测试

package com.hh.encap;

public class AccounTest {
    public static void main(String[] args) {
            Account cu=new Account("puy",200.1,"457897");
            System.out.println(cu.info());
    }
}
package com.hh.encap;

public class Account {
    private String name;
    private double account;
    private String cord;

    public Account(String name, double account, String cord) {
        this.setName(name);
        this.setAccount(account);
        this.setCord(cord);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if (name.length() ==2|| name.length() == 4||name.length()==3) {
            this.name = name;
        } else {
                System.out.println("名字的长度需要在2~4之间,默认值为冯书记");
                this.name="冯书记";
        }
    }
    public double getAccount() {
        return account;
    }

    public void setAccount(double account) {
        if(account>20)
        {
            this.account = account;
        }
        else{
            System.out.println("余额不满20,系统设置默认值为20");
            this.account=20;
        }
    }

    public String getCord() {
        return cord;
    }

    public void setCord(String cord) {
        if(cord.length()==6)
        {
            this.cord = cord;
        }
        else{
            System.out.println("你输入的密码长度不符合6位,系统默认密码位123456");
            this.cord="123456";
        }
    }
    public String info()
    {
        return "您的信息是:"+name+"余额: "+account+"密码:"+cord;
    }
}

继承

为什么需要继承?

package com.extend_;

public class Extend01 {
    public static void main(String[] args) {
        Pupil p=new Pupil();
        p.name="小明";
        p.age=10;
        p.show();
        p.setScore(90);
        p.info();
        System.out.println("=====================");
        Graduate g=new Graduate();
        g.name="cmg";
        g.age=21;
        g.show();
        g.setScore(100);
        g.info();
    }
}
package com.extend_;

public class Pupil {
    public String name;
    public int age;
    private double score;

    public void setScore(double score) {
        this.score = score;
    }
    public void show()
    {
        System.out.println("小学生"+name+"正在考试小学数学");
    }
    public void info()
    {
        System.out.println("信息如下: 姓名:"+name+"年龄:"+age+"成绩"+score);
    }
}
package com.extend_;

public class Graduate {
    public String name;
    public int age;
    private double score;

    public void setScore(double score) {
        this.score = score;
    }
    public void show()
    {
        System.out.println("大学生"+name+"正在考试大学数学");
    }
    public void info()
    {
        System.out.println("学生名:"+name+"年龄:"+age+"成绩"+score);
    }
    //两个类很多是相同
}

从这三个可以看出,代码的冗余度很高,大部分的属性和方法是意愿的,因此需要代码复用

继承的基本语法

class 子类 extends 父类
{

}
  • 子类就会自动拥有父类定义的属性和方法
  • 父类又叫超类和基类
  • 子类又叫派生类

继承的简单使用

创建一个父类将Graduate和pupil共有的属性和方法放在一起

package com.extend_.improve_;

//父类,pupil和graduate
public class Student {
    //共有属性
    public String name;
    public int age;
    private double score;
    public void setScore(double score) {
        this.score = score;
    }
    //公有方法
    public void info()
    {
        System.out.println("信息如下: 姓名:"+name+"年龄:"+age+"成绩"+score);
    }
}

子类继承

package com.extend_.improve_;

public class Graduate extends Student{
    public void show()
    {
        System.out.println("大学生"+name+"正在考试大学数学");
    }
}
package com.extend_.improve_;
//pupil继承student类
public class Pupil extends Student{
    public void show()
    {
        System.out.println("小学生"+name+"正在考试小学数学");
    }
}

细节

  • 代码复用性提高
  • 拓展性和维护性提高了
  • 子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,要通过父类提供的公共的方法去访问
  • 子类必须调用父类的构造器,完成父类的初始化
  • 如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作
  • 如果希望指定去调用父类的某个构造器,则显式的调用一下:super(参数列表)
  • super在使用时,需要放在构造器第一行
  • super()和this()都只能放在构造器第一行,因此两个方法不能共存在同一个构造器
  • Java所有类是Object类的子类
  • 父类构造器的调用不限于直接父类。将一直往上追溯到object类
  • 子类最多只能继承一个父类(直接继承),单继承机制
  • 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系

继承的本质

当子类对象创建好后,建立查找关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F3nC3cI4-1631068658032)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3eaa4575-1ba6-4cc3-874c-c5cee17d1d51/Untitled.png)]

package com.extend_;

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son=new Son();
        System.out.println(son.name);
        System.out.println(son.age);
    }
}
class Grandpa{
    String name="大头爷爷";
    String hobby="旅游";
    
}
class Father extends Grandpa{
    String name="大头爸爸";
    int age=39;
}
class Son extends Father{
    String name="大头儿子";
}
package com.extend_;

public class ExtendsTheory {
    public static void main(String[] args) {

        B b=new B();//调用B类的无参构造器
    }
}

class A{
    A()
    {
        System.out.println("a");
    }
    A(String name)
    {
        System.out.println("a name");
    }
}
class B extends A{
    B()
    {
        this("abc");
        System.out.println("b");
    }
    B(String name)
    {
        System.out.println("b name");
    }
}

输出结果

a
b name
b
  • 答案解析

    main方法里创建了b,我们看到类B是继承类A,因此创造了无参构造器后,需要跳转到父类,由于是无参输出a,然后A(String name)跳过,执行到this(“abc”),执行B(String name)输出b name,然后this("abc”)结束执行,执行输出b的语句。

package com.newkk;

public class Exercise2 {
    public static void main(String[] args) {
        C c=new C();
    }
}
class A{
    public A()
    {
        System.out.println("我是A类");
    }
}
class B extends A{
    public B()
    {
        System.out.println("我是B类的无参构造");

    }
    public B(String name)
    {
        System.out.println(name+"我是B类的有参构造");
    }
}
class C extends B
{
    public C()
    {
        this("hello");//调用本类的有参构造
        System.out.println("我是C类的无参构造");
    }
    public C(String name)
    {
        super("hahah");
        System.out.println("我是C类的有参构造");
    }

}
我是A类
hahah我是B类的有参构造
我是C类的有参构造
我是C类的无参构造

关于电脑的一个简单小例子

package com.Extendexercise3;

public class Test {
    public static void main(String[] args) {

       PC pc=new PC("intel",16,500,"IBM");
       pc.info();
       NotePad pad=new NotePad("Intel",16,500,"red");
       pad.info2();

    }
}
package com.Extendexercise3;

public class Computer {
    private String CPU;
    private double memory;
    private int disk;

    public Computer(String CPU, double memory, int disk) {
        this.CPU = CPU;
        this.memory = memory;
        this.disk = disk;
    }

    public String getCPU() {
        return CPU;
    }

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public double getMemory() {
        return memory;
    }

    public void setMemory(double memory) {
        this.memory = memory;
    }

    public int getDisk() {
        return disk;
    }

    public void setDisk(int disk) {
        this.disk = disk;
    }
    public String getDetail()
    {
        return "电脑的信息为:"+"CPU: "+CPU+"内存容量: "+memory+"硬盘:"+disk;
    }
}
package com.Extendexercise3;

public class PC extends Computer{
    private String brand;
//IDEA根据继承的原则,自动把构造器的调用写好
    public PC(String CPU, double memory, int disk, String brand) {
        super(CPU, memory, disk);
        this.brand = brand;
    }

    public String getBrand() {
        return brand;
    }

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

   public void info()
    {
        System.out.println(getDetail()+"品牌是"+brand);
    }
}
package com.Extendexercise3;

public class NotePad extends Computer{
    private String color;

    public NotePad(String CPU, double memory, int disk, String color) {
        super(CPU, memory, disk);
        this.color = color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

   public void info2()
    {
        System.out.println(getDetail()+"颜色"+color);
    }
}

super关键字

  • super代表父类的引用,用于访问父类的属性、方法、构造器
  • super能访问父类的属性和方法,但不能是private
super().方法名
super().属性
super(参数列表)用于访问构造器

super的使用细节

  • 调用父类的构造器好处:分工明确,父类属性由父类初始化
  • 当子类有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super
  • 访问n1和this.n1
  • 多个父类有同名的成员,使用super访问遵循就近原则

在这里插入图片描述

方法的重写

子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法

子类方法不能缩小类方法的访问权限

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6KI0ae3k-1631068658038)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/47cc9a74-c5cf-4096-9c40-b896b19f9fdf/Untitled.png)]

重写的案例

package com.person;

public class Person {
    private String name;
    private int age;

    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;
    }

    public String say()
    {
        return "我是:"+name+"年龄:"+age;
    }
}
package com.person;

public class Student extends Person{
    private int id;
    private double score;
    public Student(String name, int age) {
        super(name, age);
    }

    public Student(String name, int age, int id,double score) {
        super(name, age);
        this.id = id;
        this.score = score;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public String say()//super的好处
    {
        return super.say()+"id:"+id+"score"+score;//调用父类的C方法
    }
}
package com.person;

public class test {
    public static void main(String[] args) {
            Person man=new Person("王东",50);

        System.out.println(man.say());

        Student smith=new Student("smith",90,855,98.1);
        System.out.println(smith.say());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值