10.2 protected关键字

继承有如下特点:
1.一个类只能继承一个类,不支持多继承。例如A extends B,C这样是非法的。
2.子类对象能访问父类的带protected修饰符的属性和方法,protected意味着这个属性或方法可以被子类对象直接使用。
3.子类会继承父类的所有非private(protected和public)的属性和方法,这些属性也是子类的属性和方法。
例如下面的代码,Square是子类,于是Square继承了父类Rectangle的两个属性:length,height。
public class Rectangle{
    protected double length;
    protected double height;
    public double sqr(){
        return length*height;
    }
    public double cc(){
        return 2*(length+height);
    }
}
public class Square extends Rectangle{
    public Square(double length){
        this.height=length;
        this.length=length;
    }
}
public static void main(String[]args){
    Square s=new Square(4);
    System.out.println(s.sqr());
}
最终会打印16.这里Square定义了一个构造方法,接受一个参数,把这个参数赋值给父类Rectangle的length和height(长和高)的值,长和高的值一样,也就是正方形了。
在这里子类就是使用了父类的protected属性length和height,在Square里面是没有这两个属性的,但是Square仍然可以使用。 s.sqr()调用的是父类Rectangle的sqr方法,由于s是Square(正方形),也是Rectangle(矩形)的一种,所以s也是Rectangle,由此s可以调用Rectangle内所有方法。
这就是继承关系:Square是Rectangle的一种,Square的对象s也是Recangle对象!那么这个对象s当然可以调用Rectangle的方法了。事实上,可以这样写:
public static void main(String[]args){
    Rectangle sq=new Square(4);
    System.out.println(sq.cc());
}
这看上去非常奇怪,sq声明类型是Rectangle,实际调用的构造函数却是Square!sq是一个Rectangle(矩形),实际类型是Square(正方形)。反过来的话,会出语法错误。
public static void main(String[]args){
    //语法错误!
    Square sq=new Rectangle();
}

最后是关于protected的访问控制的,一个对象是否能直接访问它的protected属性,取决于这个对象的位置,例如下面的代码:
public static void main(String[]args){
    Rectangle s=new Rectangle();
    s.height=4;
    s.lenght=5;
    System.out.println(s.sqr());
}
这个main函数里面的s是一个Rectangle对象,直接修改了s的height和length值。这段代码只能在Rectangle类同一个包(package)内才不会有语法错误:
因为这个Test在abcd包,而Rectangle在abc包,所以Rectangel的对象s不能直接访问protected属性length和height,假如Test类在abc包里,这段代码就没有语法错误。

练习题

  • 完成下面的练习
    1.已知两个类,然后Apple类里面的main函数运行后,会: (2分) [选择]
    A.
    B. 打印我是Apple
    C. 打印我是Fruit
    D. 语法错误
    E. 什么都不打印
    public class Fruit{
            public void print(){
                    System.out.println( "我是Fruit");}}
    public class Apple extends Fruit{
            public static void main(String[]args){
                    Apple b=new Apple();        b.print();}}
    
    2.关于子类和父类的属性问题,以下哪个说法是正确的 (2分) [选择]
    A.
    B. 子类可以使用父类的protected属性
    C. 子类只可以使用父类的public属性
    D. 子类可以使用父类的private属性
    E. 子类可以使用父类的所有属性
    3.子类是父类的扩展 [阅读]
    子类可能会有父类没有的属性和方法,而父类并不是子类的一种,此时父类的对象是不可能知道子类增加的属性和方法的。
    假如Square的代码如下,它增加了一个size属性。代码里面s1.size=4;是正确的,s2.size=5;会有语法错误!因为s2的声明类型是Rectangle,Rectangle是没有size这个属性的。
    public class Square extends Recangle{
            
        private double size;
            
        public static void main(String[]args){
                    
            Square s1=new Square();
                    
            Recangle s2=new Square();
                    
            s1.size=4;
                    
            s2.size=5;}}
    
  • 判断题
    1.已知Square继承Rectangle,语句Rectangle s2=new Square();会导致语法错误 (2分) [判断]
    2.已知Square继承Rectangle,语句Square s2=new Rectangle();会导致语法错误 (2分) [判断]
    3.已知Square继承Rectangle,Square可以使用Rectangle的所有属性 (2分) [判断]
    4.已知Square继承Rectangle,Square可以使用Rectangle的所有protected属性 (2分) [判断]
    5.已知Square继承Rectangle,Rectangle可以使用Square的所有protected属性 (2分) [判断]
  • 编程题,需要写两个类(一个父类一个子类)
    1.设计下面的继承类 (10分) [Java多类]
    父类汽车类Vehicle,有一个double类型的属性speed代表最高速度。Vehicle类还需要有设置speed值的public方法setSpeed供子类调用            
    子类轿车类Car,它没有属性,它将使用父类的属性speed,Car有一个方法showSpeed,没有参数,没有返回值,打印这样一句话“本车的最高速度是X”,这个X就是speed属性值。
                
    这是使用两个类的测试代码
    public static void main(String[]args){    Car car=new Car();    car.setSpeed(160);    car.showSpeed();}