Java面向对象三大特性:继承、封装、多态

java封装、继承、多态笔记

1.包

1.包的命名规则

(1)只能包含数字、字母、下划线、小圆点.

(2)不能用数字开头,

(3)不能是关键字或保留字

例如:

demo.class.exec1 //错误class是关键字

demo.12a //错误,以数字开头

demo.ab12.oa // 对

命名规范实例:

一般是小写字母+小圆点(一般是com.公司名.项目名.业务模块名)

比如:

com.hspedu.oa.model;

com.hspedu.oa.controller;

举例:
com.sina.crm.user//用户模块

com.sina.crm.order//订单模块

com.sina.crm.utils //工具类


2.常用的包

一个包下,包含很多的类,java中常用的包有:

java.lang.* //lang包是基本包,默认引入,不需要再引入

java.util.* //util包,系统提供的工具包,工具类,使用 Scanner

java.net.* //网络包,网络开发

java.awt.* //是做java的界面开发,GUI


3.包引入的注意事项

一个类中最多只有一个package

package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一个package

2.访问修饰符

1.基本介绍

java提供四种访问控制修饰符号控制方法和属性(成员变量)的访问权限(范围)

1.公开级别:用public修饰,对外公开

2.受保护级别:用protected修饰,对子类和同一个包中的类公开

3.默认级别:没有修饰符号,向同一个包的类公开

4.私有级别:用private修饰,只有类本身可以访问,不对外公开

在这里插入图片描述

3.面向对象编程的三大特点:继承、封装和多态

1.封装

1.1 封装的定义

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

1.2 封装的实现步骤的三部曲

1)将属性进行私有化private【不能直接修改属性】

2)提供一个公共的(public)set方法,用于对属性判断并赋值

public void setXxx(类型参数名){
//set方法用来设置或者修改属性值
//加入数据验证的业务逻辑属性=参数名;
}

3)提供一个公共的get方法,用于获取属性的值

public XX getXxx(){//权限判断
return xx;
}
1.3封装快速入门案例

案例一:

不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。

年龄合理就设置,否则给默认‘年龄必须在1-120,年龄,工资不能直接查看,name的长度在2-6之间

package com.hspedu.encap;
//不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认
//年龄必须在1-120,年龄,工资不能直接查看,name的长度在2-6之间
public class Encapsulation {
    public static void main(String[] args) {
        Person person = new Person();
        person.name="li";
        person.setAge(10);
        person.setSalary(10000);
        System.out.println(person.info());
    }
}
class Person{
    public String name;
    private int age;
    private double  salary;

    public void  setName(String name){
        if(name.length() >=2 && name.length() <=10)
            this.name = name;
        System.out.println("不合法");
    }
    public void setAge(int age) {
        if(age < 1 || age > 120)
            System.out.println("年龄不符合条件");
        this.age = age;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public String getName(){
        return name ;
    }
    public int getAge() {
        return age;
    }
    public double getSalary() {
        return salary;
    }
    //写一个方法返回字符串
    public String  info(){
        return "信息为 name="+name+"age="+age+"salary="+salary;
    }
}

案例二:

创建程序,在其中定义两个类:Account和AccountTest类,体会Java的封装性。

1.Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)、密码(必须是六位),如果不满足,则给出提示信息,并给默认值

2.通过setXxx的方法给Account的属性赋值。

3.在AccountTest中测试

提示知识点:
String name= “”;int len = name.length();

package com.hspedu.encap;

public class Account{
    String name;
    double salary;
    String pass;

    public Account() {
    }

    public Account(String name, double salary, String pass) {
        this.name = name;
        this.salary = salary;
        this.pass = pass;
    }

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }


    public void setName(String name) {
        if(name.length() == 2 || name.length() == 3 || name.length() == 4)
            this.name = name;
    }

    public void setSalary(double salary) {

        if(salary >= 20){
            this.salary = salary;
        }else {
            this.salary = 0;
        }


    }

    public void setPass(String pass) {
        if(pass.length() == 6)
            this.pass = pass;
        else {
            System.out.println("密码错误");
            this.pass = "000000";
        }

    }

    public String getPass() {
        return pass;
    }

    public void showInfo(){
        System.out.println("name =" + name + "salary =" + salary + "pwd =" + pass);
    }
}
package com.hspedu.encap;

public class AccountTest {
    public static void main(String[] args) {
        Account account = new Account();
        account.setName("ping");
        account.setSalary(13);
        account.setPass("123456");
        account.showInfo();

    }
}

2.继承

1.继承的基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父

类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。

画出继承的示意图

在这里插入图片描述

2.继承的基本语法
class 子类 extends 父类{}

1)子类就会自动拥有父类定义的属性和方法

2)父类又叫超类,基类。

3)子类又叫派生类。

3.重点理解

1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过公共的方法去访问

拆分

(1)子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,除了父类中的私有方法继承后无法使用,其与方法都可以使用

父类

package com.hspedu.extend_.improve;
//父类,是pupil和graduate的父类
public class Student {
    //共有的属性
    public String name;
    private  double score;
    public int age;
	//共有的方法
    public void setScore(double score) {
        this.score = score;
    }
    public void showInfo(){
        System.out.println(age + "岁的" + name + "考试考了" + score);
    }
}

子类:假设只有显示的某个信息不一样,这个信息是子类特有的

package com.hspedu.extend_.improve;
public class Pupil extends Student {
    
    public void testInfo(){
        System.out.println("小学生" + name + "正在考小学数学");
    }
}
package com.hspedu.extend_.improve;

public class Graduate  extends Student{

    public void testInfo(){
        System.out.println("大学生"+ name + "正在考大学数学");
    }
}

测试

package com.hspedu.extend_.improve;

public class Test {
    public static void main(String[] args) {
        Pupil pupil = new Pupil();
        pupil.name="li";
        pupil.age = 10;
        pupil.setScore(100);
        pupil.testInfo();
        pupil.showInfo();
        System.out.println("==============");
        Graduate graduate = new Graduate();
        graduate.name = "ping";
        graduate.age = 20;
        graduate.setScore(98);
        graduate.testInfo();
        graduate.showInfo();
    }
}

(2)但是私有属性和方法不能在子类直接访问

刚才的年龄是共有属性

//如果把父类中年龄改成私有的
private int age;

//测试中的这一行代码会出错
  pupil.age = 10;

(3)解决上述问题:要通过公共的方法去访问

package com.hspedu.extend_;

public class Base {
    //不同的属性
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    //n4是私有的,Sub无法直接拿到
    private  int  n4 = 400;
    //父类中提供了一个public的方法,返回了n4,通过这个方法,Sub类中就可以拿到n4的参数
    public int getN4() {
        return n4;
    }
    //无参构造器
    public Base(){
        System.out.println("父类的无参构造器Base()被调用....");
    }
    //不同的属性
    public void Base1(){
        System.out.println("Base1()...");
    }
    void Base02(){
        System.out.println("Base2()...");
    }
    protected void  Base03(){
        System.out.println("Base03()...");
    }
    //在Sub中是无法获取的
    private void Base4(){
        System.out.println("Base4()....");
    }
    //可以通过这个方法来实现
    public void callBase4(){
        Base4();
    }
}

测试

package com.hspedu.extend_;

public class Sub extends  Base{
     public Sub(){
//         super();//默认调用父类的无参构造器,写不写都会被调用
         System.out.println("子类的无参构造器Sub()被调用...");
     }
     public void ok(){
         System.out.println("n1:"+ n1+ "\t n2:" + n2 + "\t n3:" + n3);
         //由于Base下的n4是私有的,因此无法直接拿到,但是可以将私有的属性通过共有的方法让继承后类中使用

         System.out.println("n4:"+getN4());
         Base1();
         Base02();
         Base03();
         //Base4的方法是私有的无法拿到,但是可以通过共有的方法那它在传到当前位置来
         //Base4();
         //在Base中使用了公共方法将其传入
         callBase4();

     }
}

2.子类必须调用父类的构造器,完成父类的初始化

 //尽管Sub类中的方法没有调用父类的无参构造器,但是也会显示父类无参构造器相关信息,然后显示子类的无参构造器相关信息
//上面代码的片段
public class Sub extends  Base{
     public Sub(){
//         super();//默认调用父类的无参构造器,写不写都会被调用
         System.out.println("子类的无参构造器Sub()被调用...");
     }

     public Sub(String name ){
         System.out.println("子类有参构造器Sub(String name )被调用");

     }
}

测试:
在这里插入图片描述

3.当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在

子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过[举例说明]

package com.hspedu.extend_;

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

        //尽管Sub类中的方法没有调用父类的无参构造器,但是也会显示父类无参构造器相关信息,然后显示子类的无参构造器相关信息
        Sub sub = new Sub();
        System.out.println("============");
        Sub sub1 = new Sub();
//       sub.ok();
    }
}

测试结果:默认父类无参构造器会被调用

在这里插入图片描述


指定调用构造器

public class Base {
    
    //无参构造器
//    public Base(){
//        System.out.println("父类的无参构造器Base()被调用....");
//    }
    public  Base(String name, int age){
        System.out.println("用的是父类第二个Base(String name, int age)");
    }
}
public class Sub extends  Base{
     public Sub(){
//         super();//默认调用父类的无参构造器,写不写都会被调用
         //当父类的无参构造器被覆盖时,需要指定
         //super在使用时,必须放在构造器的第一行
         //super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器里面,第一行写了super(),就不能写this()
         super("li",10);
         System.out.println("子类的无参构造器Sub()被调用...");
     }

     public Sub(String name ){
           //当父类的无参构造器被覆盖时,需要指定
         super("chen",24);
         System.out.println("子类有参构造器Sub(String name )被调用");

     }

在这里插入图片描述

4.如果希望指定去调用父类的某个构造器,则显式的调用一下: super(参数列表)

5.super在使用时,必须放在构造器第一行(super)

6.super()和 this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7.java所有类都是Object类的子类,Object是所有类的基类.

8.父类构造器的调用不限于直接父类!将一直往上追溯直到Object类(顶级父类)

9.子类最多只能继承一个父类(指直接继承),即java中是单继承机制。

思考:如何让A类继承B类和C类?

答案:A继承B,B在继承C

继承的本质:

/*
* (1)先查看子类是否有该属性
* (2)如果子类有该信息,并且可以访问,则返回信息
* (3)如果子类没有该属性,就看父类有没有这个属性,如果父类有该属性,并且可以访问,则返回父类的该信息
* (4)如果父类的该属性不可以访问,继续找上一级的父类,直到找到object
* */

在这里插入图片描述

问题:如果对象son要访问age这一属性,但是父类Father的age是私有的,爷爷类Grandpa的age是共有的,那么他能拿到爷爷的age吗?

不能!因为son在访问Father类的时候已经找到age这一 个属性了,但是由于是私有的无权访问,拿不到结果。它已经找到了,就不在想上找了,不会说无权访问就直接拿到grandpa类中的age属性。

4. super关键字

super代表父类的引用,用于访问父类的属性、方法、构造器

●基本语法

1.访问父类的属性,但不能访问父类的private属性【案例】 super.属性名;

2.访问父类的方法,不能访问父类的private方法【案例】super.方法名(参数列表);

3.访问父类的构造器(这点前面用过):super(参数列表);只能放在构造器的第一句,只能出现一句!

在这里插入图片描述
Super关键字
1.调用父类的构造器的好处(分工明确父类属性由父类初始化,子类的属性由子类初始化)
2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果!
3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。A->B->C,当然也需要遵守访问权限相关的规则

5.Super和this关键

在这里插入图片描述

3. 重写/覆盖

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称、返回类型、参数一样,那么我们就说子类的这个方法覆盖了父类的方法

1.子类的方法的参数,方法名称,要和父类方法的参数,方法名称完全一样。

2子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类

比如父类返回类型是Object ,子类方法返回类型是String

【演示】

public class Animal {
    public void ask(){
        System.out.println("动物在叫唤.....");
    }
    public Object m1(){
        return null;
    }
}
public class Dog extends Animal {

    public void cry(){
        System.out.println("wangwang......");
    }
    //和public object m1()构成重写
    public String m1(){
        return null;
    }
}

【练习一】:

1.编写一个Person类,包括属性 private (name、age),构造器、方法say(返回自我介绍的字符串)。
2.编写一个Student类,继承Person类,增加id、score属性private,以及构造器,定义say方法(返回自我介绍的信息)。
3.在main中,分别创建Person和Student对象,调用say方法输出自我介绍。
体会在子类中使用super()的好处
1.Person类,父类

package com.hspedu.override_;
public class Person {
    private  String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String  say(){
        return "我的名字是"+ name + "年龄是:" + age;
    }

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

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

2.studen类

package com.hspedu.override_;

public class Student extends Person {
    private  int id;
    private  double score;

    public Student(String name, int age, int id, double score) {
        super(name, age);
        this.id = id;
        this.score = score;
    }
    public String say(){
        return super.say() + "id= "+ id + "score = " +score;
    }
    public void setId(int id) {
        this.id = id;
    }

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

    public int getId() {
        return id;
    }

    public double getScore() {
        return score;
    }
}

3.测试

package com.hspedu.override_;
public class MainT {
    public static void main(String[] args) {
        Person person = new Person("li",18);
        System.out.println(person.say());
        System.out.println("====");
        Student student = new Student("li",18,2203,80);
        System.out.println(student.say());

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值