面向对象的三特性

本文详细介绍了面向对象编程的三大特性:封装、继承和多态,以及访问修饰符的作用。通过实例展示了如何使用private封装属性并提供getter/setter方法,以及如何在子类中重写父类方法。此外,还阐述了继承的概念,子类如何调用父类的方法和属性,以及多态的应用场景。最后,讨论了instanceof关键字的用途。
摘要由CSDN通过智能技术生成

面向对象的三特性

1. 封装

    String name="da";
    int age=3000;
    char sex='男';
    double score=15.6;

在对象的外部,为对象的属性赋值,可能存在非法数据的录入。所以我们要控制属性的赋值。

使用private封装属性,get、set获取、设置属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1glc8uK-1629479583906)(_v_images/20210812153937980_11156.png =496x)]

package work;

/**
 * @Author night
 * @Date 2021/8/12 11:32
 */
class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.setAge(1500);
        student.sex = 'y';
        student.name = "da";
        student.score = 99.5;
        student.sayHi();
    }
}

public class Student {
    String name;
    private int age;
    char sex;
    double score;

    //默认构造方法
    public Student() {
    }

    //age的get方法:获取age值
    public int getAge() {
        return age;
    }

    //age的set方法:设置age值
    public void setAge(int age) {
        //控制age的值
        if (age > 0 && age <= 130) {
            this.age = age;
        } else {
            this.age = 18;
        }
    }

    //输出方法
    public void sayHi() {
        System.out.println("姓名:" + this.name + "年龄:" + this.age + "性别:"
                + this.sex + "分数:" + this.score);
    }
}

使用private封装age属性,并且添加getAge、setAge方法用于获取、设置age的值,然后在setAge方法中对age的值进行控制。
案例:

需求:
实现银行功能

用户输入正确卡号和密码后可执行以下操作
菜单如下:1.存款2.取款3.转账4.查询余额5.修改密码0.退出

分析:
    User类(cardNo、identity、username、password、phone、balance)
    Bank类主要包括以下功能
        初始化用户(initial)
        用户登录(login)
        显示菜单(showMenu)
        存款(save)、取款(withDraw)、转账(trans)、查询余额(query)、修改密码(modifyPassword)
package work;

import java.util.Scanner;

/**
 * @Author night
 * @Date 2021/8/12 15:43
 */
class TestCard {
    public static void main(String[] args) {
        Card card = new Card();
        card.initial();
    }
}

public class Card {
    /**
     * 卡号、身份证号码、姓名、密码、联系方式、余额
     */
    private String cardNo;
    private String identity;
    private String username;
    private String password;
    private String phono;
    private double balance;
    //因为经常使用,直接创建实例变量,在全局中都可以使用
    Scanner scanner = new Scanner(System.in);

    public void initial() {
        System.out.println("开始注册用户信息:");
        System.out.print("请输入姓名:");
        username = scanner.next();
        System.out.print("请输入密码:");
        password = scanner.next();
        System.out.print("请输入身份证号码:");
        identity = scanner.next();
        System.out.print("请输入联系方式:");
        phono = scanner.next();
        System.out.print("请输入银行卡号:");
        cardNo = scanner.next();
        System.out.print("请输入余额:");
        balance = scanner.nextDouble();

        System.out.println("********用户信息如下********");

        System.out.println("姓名:" + username + "\t\t" + "密码:" + password + "\t\t" + "身份证号码:" + identity);
        System.out.println("联系方式:" + password + "\t\t" + "卡号:" + cardNo + "\t\t" + "余额:" + balance);
        login();
    }

    /**
     * 登录方法
     */
    public void login() {
        String name;
        String pwd;
        System.out.println("********请登录********");
        System.out.print("请输入姓名:");
        name = scanner.next();
        System.out.print("请输入密码:");
        pwd = scanner.next();
        //校验密码是否正确
        if (name.equals(username) && pwd.equals(password)) {
            System.out.println("********登录成功,欢迎你********");
            showMenu();
        } else {
            System.out.println("********登录失败,请重新登录********");
            login();
        }
    }

    //显示菜单方法
    public void showMenu() {
        System.out.println("1、存款  2、取款  3、转账  4、余额查询 5、修改密码  0、退出");
        int choose;
        System.out.print("请选择业务:");

        choose = scanner.nextInt();
        switch (choose) {
            case 1:
                System.out.println("********进入存款********");
                save();
                break;
            case 2:
                System.out.println("********进入取款********");
                withDraw();
                break;
            case 3:
                System.out.println("********进入转账********");
                trans();
                break;
            case 4:
                System.out.println("********查询余额********");
                query();
                break;
            case 5:
                System.out.println("********修改密码********");
                modifyPassword();
                break;
            case 0:
                return;

        }
    }

    //存款方法
    public void save() {
        System.out.print("请输入存进的金额:");
        int money = scanner.nextInt();
        balance = balance + money;
        System.out.print("您的余额:" + balance);
        System.out.println();
        showMenu();
    }

    //取款方法
    public void withDraw() {
        System.out.print("请输入取出的金额:");
        int money = scanner.nextInt();
        //取款数大于余额无法取款
        if (money > balance) {
            System.out.println("余额不足,请重新输入");
            withDraw();
        }
        balance = balance - money;
        System.out.print("您的余额:" + balance);
        System.out.println();
        showMenu();
    }

    //转账
    public void trans() {
        System.out.print("请输入转入的卡号:");
        String orderCardNo = scanner.next();
        //自己不能向自己的卡内转账
        if (orderCardNo.equals(cardNo)) {
            System.out.println("自己不能向自己的卡内转账");
            trans();
        }
        System.out.print("请输入转入的金额:");
        double money = scanner.nextDouble();
        //转账数大于余额无法转账
        if (money > balance) {
            System.out.println("余额不足,请重新输入");
            trans();
        }
        balance = balance - money;
        System.out.print("您已向卡号为:" + orderCardNo + "转入" + money + "您卡内余额为" + balance);
        System.out.println();
        showMenu();
    }

    public void query() {
        System.out.print("您的余额:" + balance);
        System.out.println();
        showMenu();
    }

    String pwd1 = null;

    public void modifyPassword() {
        System.out.println("请输入密码:");
        pwd1 = scanner.next();
        System.out.println("请确认密码:");
        String pwd2 = scanner.next();
        //校验两次输入的密码是否相同
        if (pwd1.equals(pwd2)) {
            password = pwd1;
        } else {
            System.out.println("两次密码输入不一致,请重新输入:");
            modifyPassword();
        }
        System.out.print("该账号的密码:" + password);
        System.out.println();
        showMenu();
    }

    //无参构造方法
    public Card() {
    }

    //get and set
    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    public String getIdentity() {
        return identity;
    }

    public void setIdentity(String identity) {
        this.identity = identity;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhono() {
        return phono;
    }

    public void setPhono(String phono) {
        this.phono = phono;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

2. 访问修饰符

本类同包非同包子类其它
private×××
default××
protected×
public

3. 继承

子类继承父类后,子类可以使用父类中的属性和方法,也可定义子类独有的属性和方法。

语法:
class子类extends父类{}/∥定义子类时,显示继承父类
public class inherit {
    public static void main(String[] args) {
        //实例化子类
        Dog dog = new Dog();
        //子类通过继承调用父类的属性,从而给自己赋值
        dog.name = "狗";
        dog.age = 2;
        dog.sex = "公";
        dog.hairColor="白色";
        System.out.println(dog.name+dog.hairColor+dog.sex+dog.age);
        //调用子类特有的方法
        dog.run();
        //子类调用父类的方法
        dog.eat();
        dog.sleep();
    }
}
//父类
class Animal {
    public String name;
    public int age;
    public String sex;

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

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

//子类使用extends继承父类
class Dog extends Animal {
    public String hairColor;
    //子类特有的方法
    public void run() {
        System.out.println("跑.....");
    }
}

不可继承

构造方法:
    类中的构造方法,只负责创建本类对象,不可继承。
private修饰的属性和方法:(权限不足)
    访问修饰符的一种,仅本类可见。
父子类不在同一个package中时,default修饰的属性和方法:(权限不足)
    访问修饰符的一种,仅同包可见。

4. 方法覆盖

方法覆盖原则:
    方法名称、参数列表、返回值类型必须与父类相同。
    访问修饰符不能比父类更严格。
    
方法覆盖的执行:
    子类覆盖父类方法后,调用时优先执行子类覆盖后的方法。
public class inherit {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
    }
}

//父类
class Animal {
    public String name;
    public int age;
    public String sex;

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

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

//子类
class Dog extends Animal {
    //重写父类eat方法
    @Override
    public void eat() {
        System.out.println("吃狗粮");
    }

    //子类特有方法
    public void run() {
        System.out.println("跑.....");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RsoWF1bJ-1629479583908)(_v_images/20210813090902401_6814.png =495x)]

super关键字

在子类中,可直接访问从父类继承到的属性和方法,但如果父子类的属性或方法存在重名(属性遮蔽、方法覆盖)时,需要加以区分,才可专项访问。

当子类继承父类,子类想要使用父类方法里面的方法体,可以使用super关键字完成
示例:
Father类的show方法输出Father,Son类的show方法输出Son,如果实例化Son调用show方法并且想输出Father,就需要使用super.show();,这里的show方法调用的就是Father类的show方法

public class superInherit {
    public static void main(String[] args) {
        Son son = new Son();
        son.show();
    }
}

//父类
class Father {
    public void show() {
        System.out.println("Father");

    }
}

//子类
class Son extends Father {
    public void show() {
        //调用父类的show方法
        super.show();
        System.out.println("Son");
    }
}

不仅可以调用方法,还可以调用属性。
public class superInherit {
    public static void main(String[] args) {
        Son son = new Son();
        son.print();

    }
}

//父类
class Father {
    int age = 10;
}

//子类
class Son extends Father {
    int age = 20;

    public void print() {
        int age = 30;
        System.out.println("局部变量:" + age);
        System.out.println("实例变量:" + this.age);
        System.out.println("父类变量:" + super.age);
    }
}
super还可以调用父类的无参构造方法
public class superInherit {
    public static void main(String[] args) {
        Son son = new Son();
        son.print();
    }
}

//父类
class Father {
    public Father() {
        System.out.println("父类默认构造方法");
    }
}

//子类
class Son extends Father {
    public Son() {
        //调用父类默认构造方法
        super();
        System.out.println("子类默认构造方法");
    }

    public void print() {
        System.out.println("子类特有方法");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D5hWJ3tG-1629479583909)(_v_images/20210813094815662_20472.png =480x)]

在子类中使用super();可以调用父类默认的构造方法,调用时必须放在第一行,和this一样。
程序执行顺序是:父类构造方法、子类构造方法、子类特有方法

子类还可以调用父类带参的构造方法

public class superInherit {
    public static void main(String[] args) {
        //实例化子类,并且调用的是带参构造方法,不是默认的无参构造方法
        Son son = new Son(100, 200, 300);
        son.print();
    }
}

//父类
class Father {
    int num1;
    int num2;

    public Father() {
        System.out.println("父类默认构造方法");
    }

    //父类重载自己的构造方法:两个参数
    public Father(int num1, int num2) {
        this.num1 = num1;
        this.num2 = num2;
        System.out.println(num1 + "\t" + num2);
    }
}

//子类
class Son extends Father {
    int num3;

    //子类重载自己的构造方法
    public Son(int num1, int num2, int num3) {
        //调用父类的带参构造方法
        super(num1, num2);
        this.num3 = num3;
        System.out.println(num1 + "\t" + num2 + "\t" + num3);
    }

    public Son() {
        //调用父类默认构造方法
        super();
        System.out.println("子类默认构造方法");
    }

    public void print() {
        System.out.println("子类特有方法");
    }
}

this和super的区别

this表示当前对象引用,调用本类(包括继承)的属性、方法、本类构造方法
super表示父类对象引用,调用父类的属性、方法、构造方法
this和super不能同时使用,因为两个都必须在首行
public class superInherit {
    public static void main(String[] args) {
        //实例化子类,并且调用的是带参构造方法,不是默认的无参构造方法
        new Son(10);
    }
}

//父类
class Father {
    public Father() {
        System.out.println("父类默认构造方法");
    }
}

//子类
class Son extends Father {

    //子类重载自己的构造方法
    public Son(int num1) {
        this();
        System.out.println(num1);
    }

    public Son() {
        //调用父类默认构造方法
        super();
        System.out.println("子类默认构造方法");
    }
}

执行流程:当实例化子类特有方法时,首先调用子类特有的方法,子类特有方法第一行是this();所以会去调用子类的无参构造方法,子类的无参构造方法第一行是super();所以调用父类的无参构造方法,父类的无参构造方法输出:父类默认构造方法,执行结束后掉头到子类无参构造方法执行输出:子类默认构造方法,执行结束后再掉头到子类带参构造方法,因为主方法在实例化是传入参数10,所以现在带参构造方法的num1=10,程序执行输出10。

5. 多态

概念:父类引用指向子类对象,从而产生多种形态。

多态:二者具有直接或间接的继承关系时,父类引用可指向子类对象
public class Polymorphism {
    public static void main(String[] args) {
        //向上转型
        Animal animal = new Dog();
        animal.age = 2;
        animal.bread = "金毛";
        animal.sex = "公";
        animal.eat();
        System.out.println(animal.sex + animal.bread + animal.sex);
        //向下转型
        ((Dog) animal).run();
        ((Dog) animal).furColor = "白色";
        System.out.println(((Dog) animal).furColor);
    }
}

class Animal {
    String bread;
    int age;
    String sex;

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

class Dog extends Animal {
    String furColor;

    public void eat() {
        System.out.println("吃狗粮");
    }

    public void run() {
        System.out.println("跑......");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R1w1NugH-1629479583912)(_v_images/20210813110458033_13396.png =280x)]

多态的应用

场景一:
使用父类作为方法形参实现多态,使方法参数的类型更为宽泛。

public class Polymorphism {
    public static void main(String[] args) {
        Master master = new Master();
        master.name = "jack";
        //master.feed(new Dog());
        Dog dog = new Dog();
        master.feed(dog);

    }
}

//主人类
class Master {
    String name;
//将动物类直接作为参数
    public void feed(Animal animal) {
        System.out.println(name + "喂食");
        //调用eat方法,至于是谁的eat就需要看feed从参数是谁,如果是dog就是dog的feed方法
        animal.eat();
    }
}
//动物类:父类
class Animal {

    public void eat() {
        System.out.println("吃......");
    }
}
//狗狗类:子类
class Dog extends Animal {
    public void eat() {
        System.out.println("狗狗开始吃狗粮");
    }
}

场景二:使用父类作为方法返回值实现多态,使方法可以返回不同子类对象

public class Polymorphism {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int choose = scanner.nextInt();
        Master master = new Master();
        //choose通过buy方法赋值type=choose,if会选择type实现实例化不同的子类。
        // 如tyepe是1就会实例化 Animal animal =new Dog();然后返回给return animal;(返回的是类型,不是1)
        // 在通过if判断是否是空。。。
        Master.Animal animal = master.buy(choose);
        if (animal != null) {
            System.out.println("购买成功");
            //animal不是空,通过instanceof判断animal类型
            if (animal instanceof Master.Dog) {
                //将animal赋值给dog,现在程序想调用子类方法,但是dog是Dog类,animal是Animal类,所以需要强转
                Master.Dog dog = (Master.Dog) animal;
                //调用Dog的eat();
                dog.eat();
            } else if (animal instanceof Master.Bird) {
                Master.Bird bird = (Master.Bird) animal;
                bird.eat();
            }
        } else {
            System.out.println("购物失败");
        }
    }
}

//主人类
class Master {

    public Animal buy(int type) {
        Animal animal = null;
        if (type == 1) {
            animal = new Dog();
        } else if (type == 2) {
            animal = new Bird();
        }
        return animal;
    }

    //动物类:父类
    class Animal {

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

    //狗狗类:子类
    class Dog extends Animal {
        public void eat() {
            System.out.println("狗狗开始吃狗粮");
        }
    }

    class Bird extends Animal {
        public void eat() {
            System.out.println("鸟开始吃虫子");
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xbtTIj01-1629479583913)(_v_images/20210813115140776_967.png =370x)]

instanceof关键字
判读对象的数据类型,返回booolean类型结果
语法:
类型A instanceof 类型B

示例:判断animal是不是Bird类型
if (animal instanceof Bird) {}

6. 总结

继承:子类继承父类,可以使用父类的方法和属性
重写:子类继承父类,子类可以有自己的特有方法、属性,也可以调用父类的方法、属性。子类指向自己:Dog dog=new Dog();
多态:父类引用指向子类对象,从而产生多种形态。
    子类继承父类,子类可以有自己的特有方法、属性。父类指向子类:Animal animal=new Dog();    
    向上转型:父类调用子类和自己共有的方法。自动类型转换Animal animal=new Dog();     animal.eat();
    向下转型:父类调用子类特有的方法。强制类型转换:Animal animal=new Dog();    ((Dog) animal).run();
两种应用场景
    1、使用父类作为方法形参,实现多态
    2、使用父类作为方法返回值,实现多态
作用
    1、屏蔽子类间的差异
    2、灵活、耦合度低

d extends Animal {
public void eat() {
System.out.println(“鸟开始吃虫子”);
}
}
}

[外链图片转存中...(img-xbtTIj01-1629479583913)]
#### instanceof关键字

    判读对象的数据类型,返回booolean类型结果
    语法:
    类型A instanceof 类型B
示例:判断animal是不是Bird类型
`if (animal instanceof Bird) {}`
## 6. 总结
    继承:子类继承父类,可以使用父类的方法和属性
    重写:子类继承父类,子类可以有自己的特有方法、属性,也可以调用父类的方法、属性。子类指向自己:Dog dog=new Dog();
    多态:父类引用指向子类对象,从而产生多种形态。
        子类继承父类,子类可以有自己的特有方法、属性。父类指向子类:Animal animal=new Dog();    
        向上转型:父类调用子类和自己共有的方法。自动类型转换Animal animal=new Dog();     animal.eat();
        向下转型:父类调用子类特有的方法。强制类型转换:Animal animal=new Dog();    ((Dog) animal).run();
    两种应用场景
        1、使用父类作为方法形参,实现多态
        2、使用父类作为方法返回值,实现多态
    作用
        1、屏蔽子类间的差异
        2、灵活、耦合度低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值