Java面向对象03:三大特性

封装

属性私有,get/set

  • 程序设计追求”高内聚,低耦合“:高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合就是仅暴露少量的方法给外部使用
  • 通常,应禁止直接访问一个对象的属性,而应通过操作接口来访问,这称为信息隐藏
/*
1. 提高程序的安全性,保护数据
2. 隐藏代码的实现细节 
3. 统一接口
4. 增强系统可维护性
 */
public class Hello {
    public static void main(String[] args) {
        Student xm = new Student();
//        xm.name = "小明";  //name属性是privat私有类型,因此对象不能直接通过属性名调用
        xm.setName("小明");  //只能通过set方法进行赋值
        System.out.println(xm.getName());  //只能通过get方法获取值
        xm.setGender('男');
        System.out.println(xm.getGender());
    }
}

class Student{
    private String name;
    private char gender;

    public String getName() {  //定义私有属性专用的赋值和调用方法,快捷键alt + insert
        return name;
    }

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

    public char getGender() {
        return gender;
    }

    public void setGender(char gender) {
        if (gender == '男' | gender == '女'){  //私有属性的set方法可以定义一些规则,避免不合法的信息输入
            this.gender = gender;
        }
        else{
            this.gender = '无';
        }
    }
}

继承

继承的本质是对某一批类的抽象,是类与类之间的一种关系,子类扩展父类,使用关键字extends表示

Java中类只有单继承,没有多继承,且被final修饰的类不可被继承。所有类都直接或间接继承Object类

/*
四种修饰符:
1. public,需要被继承时使用
2. private,一般私有属性会用到
3. protected
4. default,默认不写
 */
public class Father {
    public static void main(String[] args) {
        Son xm = new Son();
        //父类的say()方法子类对象可以直接调用
        xm.say();  
//        xm.money;  //父类的私有属性,子类无法直接继承
        //私有属性通过get方法调用
        System.out.println(xm.getMoney());  
    }
    private int money = 1;
    
    public int getMoney() {
        return money;
    }
    
    public void say() {
        System.out.println("可以说话");
    }
}

class Son extends Father{
    //子类继承父类的所有方法
}

super关键字

public class Hello {
    public static void main(String[] args) {
        Son son = new Son();
        son.method("ty");
    }
}

class Father {
    Father(){
        System.out.println("父类的无参构造方法");
    }
    
    Father(String name){
        System.out.println("父类的有参构造方法");
    }
    protected String name = "tyy";
}

class Son extends Father {
    Son (){
//        super();  //默认先隐式调用父类的无参构造方法,再执行子类的构造方法
        System.out.println("子类的无参构造方法");
//        super(name);  //如果父类没有无参构造方法,则必须在子类显式调用父类的有参构造方法,且必须写在第一行,否则报错。但子类的构造方法也要放在第一行,产生了冲突。因此就算不需要无参构造器,也要写出来
    }
    protected  String name = "tty";
    
    public void method(String name){
        System.out.println(name);  //ty
        System.out.println(this.name);  //tty,this关键字特指本类的属性
        System.out.println(super.name);  //tyy,如果子类和父类的属性或方法重名,则通过super关键字来特指父类的
    }
}

方法重写

重写的前提是有继承关系,重写的目的就是实现多态,让子类能拓展父类的功能

  • 只能重写父类的非静态、非常量、非私有方法
  • 方法名必须相同
  • 参数列表必须相同
  • 修饰符:范围可以扩大但不能缩小(private --> default --> protected --> public)
  • 抛出的异常:范围可以缩小但不能扩大
public class Hello {
    public static void main(String[] args) {
        //父类引用f可以指向子类对象,但只能调用自己的方法(丢失了子类的方法和属性),只有子类重写了父类的方法,才能调用子类的方法,才能达到拓展的目的
        Father f = new Son();
        Son s = new Son();

        //子类引用不可以直接指向父类,除非强制转换(Son ss = (Son) new Father();)
//        Son ss = new Father();
        //父类引用不能直接调用子类的方法,除非强制转换( ((Son) f).own();)或者该方法是重写的
//        f.own();
        
        f.test();  //子类的非静态test方法,test()方法被重写了,父类引用可以调用子类的方法了
        s.test();  //子类的非静态test方法
    }
}

class Father {
    public void test(){
        System.out.println("父类的非静态test方法");
    }
}

class Son extends Father {
    //当子类重写了父类的方法时,父类引用只要指向不同的子类对象,就可以调用子类的该方法,实现了不同子类拓展父类功能的目的,这称为重写。快捷键alt + insert
    @Override
    public void test() {
        System.out.println("子类的非静态test方法");
    }

    public void own(){
    }
}

注意:不能重写父类的静态方法

当子类定义相同的静态方法时,实际上只是将父类中的该同名方法进行了隐藏,父类和子类中含有的其实是两个没有关系的方法,父类也无法调用子类的该方法(也可以理解为,静态方法是不需要继承的,可以直接用类名调用,因此不满足重写的条件)

多态

即同一方法可以根据发送对象的不同而采用多种不同的行为方式,也就是重写方法的目的,注意父类的属性和静态方法是没有多态的

一个对象的实际类型是确定的,但可以指向对象的引用类型有很多,多态体现为父类引用可以指向自己的多个子类对象,实现了对不同对象实现不同功能的要求

多态存在的条件

  • 有继承关系

  • 子类需要重写父类方法

  • 父类引用指向子类对象(向上转型)

instanceof关键字

  • instanceof关键字判断对象是否属于某个类

类型转换

  • 父类引用想要调用子类的方法,需要强制转换为子类
  • 子类也可以转换为父类,但是会丢失自己的方法
public class Hello {
    public static void main(String[] args) {
        //向上转型,丢失了子类的方法和属性
        Father s1 = new Son();
        Son s2 = new Son();
        
        //子类重写了父类的方法,因此父类可以调用子类的方法
        s1.print();
        s2.print();
        
        Father s3 = s2;
//        s3.own();  //子类转换为父类后,丢失了子类本身的方法,不能再调用own()
        
        //对不同子类,调用同一个方法的实现的功能不同,实现了多态
        Father s4 = new Son2();
        s4.print();

        System.out.println(s1 instanceof Father);  //true,instanceof关键字判断对象是否属于某个类或其子类
        System.out.println(s1 instanceof Son);  //true
        System.out.println(s2 instanceof Father);  //true
        System.out.println(s2 instanceof Son);  //true
    }
}

class Father {
    public void print(){
        System.out.println("Father的方法");
    }
}

class Son extends Father {
    @Override
    public void print() {
        System.out.println("Son的方法");
    }

    public void own(){
        System.out.println("子类自己的方法");
    }
}

class Son2 extends Father {
    @Override
    public void print() {
        System.out.println("Son2的方法");
    }
}
posted @ 2021-09-07 14:06  振袖秋枫问红叶  阅读(57)  评论(0)    收藏  举报