Java核心卷 卷一 自我笔记 5.3继承-------抽象类、受保护访问

抽象类
如果自下而上在类的继承层次结构中上移,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看,父类更加通用,人们只将它作为派生其他类的基类,而不作为想使用的特定的实例类。
为什么要花费精力进行抽象?因为每个人都有一些诸如姓名这样的属性。学生与雇员都有姓名属性,因此可以将getName方法放置在位于继承关系较高层次的通用父类中。
现在,我们增加一个getDescription方法,它可以返回一个人的简短描述。我们可以看出,在Student类和Employee类中实现这个方法很容易,但在Person中,除了姓名之外,其他的一无所知。这时,我们就可以使用abstract关键字。

public abstract String getDescription();

包含一个或者多个抽象方法的类本身必须被声明为抽象的。

public abstract class Person(){
	...
	public abstract String getDescription();
	...
}

除了抽象方法之外,抽象类还可以包含具体数据和具体方法。例如:

public abstract class Person(){
	private String name;
	public Person(String name){
		this.name=name;
	}
	public abstract String getDescription();
	public String getName(){
		return name;
	}
}

通常,在抽象类中不能包含具体方法。建议尽量将通用的域和方法放在父类中。
抽象方法充当着占位的角色,他们的具体实现在子类中。扩展抽象类有两种选择。一种是在抽象类中定义部分抽象类方法或不定义抽象类方法,这样就必须将子类也标记为抽象类;另一种是定义全部的抽象方法,这样一来,子类就不是抽象的了。
类即使不含抽象方法,也可以将类声明为抽象类。
抽象类不能被实例化。也就是说,如果将一个类声明为abstract,就不能创建这个类的对象,但可以创建一个具体子类的对象。
需要注意的是,可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象。例如:

Person p=new Student("aaa","bbb");

这里的p是一个抽象类Person 的变量,Person 引用了一个非抽象子类Student的实例。

我们以一个例子看一下:

public class PersonTest {
    public static void main(String[] args) {
        Person[] p = new Person[2];
        p[0]=new Employee("aaa",1000,1998,5,1);
        p[1]=new Student("bbb","ppp");
        for (Person person : p) {
            System.out.println(person.getName()+","+ person.getDescription());
        }

    }
}

public abstract class Person {
    public abstract String getDescription();
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class Employee extends Person {
    private double salary;
    private LocalDate hireday;

    public Employee(String name, double salary, int year,int month,int day) {
        super(name);
        this.salary = salary;
        this.hireday = LocalDate.of(year,month,day);
    }

    public void raiseSalary(double bypercent){
            double raise=salary*bypercent/100;
            salary+=raise;
    }

    @Override
    public String getDescription() {
        return String.format("an employee with a salary of $%.2f",salary);
    }

    public double getSalary() {
        return salary;
    }

    public LocalDate getHireday() {
        return hireday;
    }
}

public class Student extends Person {
    private String major;

    public Student(String name, String major) {
        super(name);
        this.major = major;
    }

    @Override
    public String getDescription() {
        return "a student majoring in "+major;
    }
}

受保护访问
有些时候,我们希望父类中某些方法允许被子类访问,或允许子类的方法访问父类的某个域。为此,需要将执行方法或域声明为protected。例如,如果将父类Employee中的hireDay声明为protected,而不是私有的,Manager中的方法就可以访问它。
不过,Manager类中的方法只能够访问Manager对象中的hireDay域,而不能访问其他Employee对象中的这个域。这种限制有利于避免滥用受保护机制,使得子类只能获得访问受保护域的权利。
在实际应用中,要谨慎使用protected属性。因为这违背了oop提倡的数据封装原则。受保护的方法更具有实际意义。如果需要限制每个方法的使用,就可以将它声明为protected。这表明子类得到信任,可以正确地使用这个方法,而其他类不行。
我们归纳一下Java用于控制可见性的4个访问修饰符:

  1. 仅对本类可见——private
  2. 对所以类可见——public
  3. 对本包和所有子类可见——protect
  4. 对本包可见——默认,不需要修饰符。
发布了59 篇原创文章 · 获赞 6 · 访问量 988

猜你喜欢

转载自blog.csdn.net/weixin_43790623/article/details/102874808