面向对象‘继承’——JAVA

@月月鸟
在《Think in java》中有这样一句话:复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情。
在这句话中最引人注目的是“复用代码”,尽可能的复用代码使我们程序员一直在追求的,现在来介绍一种复用代码的方式,也是java三大特性之一、继承。
在这里插入图片描述
继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。

继承所描述的是“is-a”的关系,如果有两个对象A和B,若可以描述为“A是B”,则可以表示A继承B,其中B是被继承者称之为父类或者超类,A是继承者称之为子类或者派生类。

继承定义了类如何相互关联,共享特性。对于若干个相同或者相识的类,我们可以抽象出他们共有的行为或者属相并将其定义成一个父类或者超类,然后用这些类继承该父类,他们不仅可以拥有父类的属性、方法还可以定义自己独有的属性或者方法。

同时在使用继承时需要记住三句话:

     1、子类拥有父类非private的属性和方法。

     2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

    3、子类可以用自己的方式实现父类的方法。(以后介绍)。

通过前面我们知道子类可以继承父类的属性和方法,除了那些private的外还有一样是子类继承不了的—构造器。对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可。

构造器

对于子类而已,其构造器的正确初始化是非常重要的,而且当且仅当只有一个方法可以保证这点:在构造器中调用父类构造器来完成初始化,而父类构造器具有执行父类初始化所需要的所有知识和能力。

public class Person {
    protected String name;
    protected int age;
    protected String sex;
    
    Person(){
        System.out.println("Person Constrctor...");
    }
}

public class Husband extends Person{
    private Wife wife;

    Husband(){
        System.out.println("Husband Constructor...");
    }
    
    public static void main(String[] args) {
        Husband husband  = new Husband();
    }
}

输出:
Person Constrctor...
Husband Constructor...

通过这个示例可以看出,构建过程是从父类“向外”扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,这就是java的聪明之处:编译器会默认给子类调用父类的构造器。

但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器

public class Person {
    protected String name;
    protected int age;
    protected String sex;
    
    Person(String name){
        System.out.println("Person Constrctor-----" + name);
    }
}

public class Husband extends Person{
    private Wife wife;

    Husband(){
        super("chenssy");
        System.out.println("Husband Constructor...");
    }
    
    public static void main(String[] args) {
        Husband husband  = new Husband();
    }
}

Output:
Person Constrctor-----chenssy
Husband Constructor...

所以综上所述:对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。

protected关键字

private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。这个时候就需要使用到protected。

对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。

public class Person {
    private String name;
    private int age;
    private String sex;

    protected String getName() {
        return name;
    }

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

    public String toString(){
        return "this name is " + name;
    }
    
    /** 省略其他setter、getter方法 **/
}

public class Husband extends Person{
    private Wife wife;

    public  String toString(){
        setName("chenssy");    //调用父类的setName();
        return  super.toString();    //调用父类的toString()方法
    }

    public static void main(String[] args) {
        Husband husband = new Husband();
        
        System.out.println(husband.toString());
    }
}

Output:
this name is chenssy

supper关键字

引用父类中所隐藏的语法格式例如以下:

super(参数列表)或super.方法名(参数列表)

以下通过代码展示一下super的使用方法:

public class Demo1 {

	public static void main(String[] args) {
		SubClass_A sc=new SubClass_A(2,3);
		System.out.println(sc.i);// 3
		System.out.println(sc.j);// 1

	}

}
class SuperClass_A
{
	public int i=0;
	public int j=0;
	public SuperClass_A()
	{
		j=1;
	}
}
class SubClass_A extends SuperClass_A
{
	public int i;
	SubClass_A(int a,int b)
	{
		super();
		i=b;
	}
}

方法重写

方法的重写:

1、在子类中可以根据需要对从基类中继承来的方法进行重写。

2、重写的方法和被重写的方法必须具有相同方法名称、参数列表和返回类型。(注:返回值可以为父类中返回值的子类型.参数若为子类,则不是重写是重载)

3、重写方法不能使用比被重写的方法更严格的访问权限。

4.、重写方法不能声明抛出比被重写方法范围更大的异常类型。

          总结:重写是子类对所继承父类相同方法的一种更改,这个更改需要遵循格式按照父类的格式,访问权限,抛出异常等等,都在父类方法控制范围内,内部具体实现可以实现不同的效果。
*
 * 重写要遵循"两同两小一大"原则:
 * 1)两同:
 *   1.1)方法名相同
 *   1.2)参数列表相同
 * 2)两小:
 *   2.1)子类方法的返回值类型小于或等于父类的
 *       2.1.1)void时,必须相同
 *       2.1.2)基本类型时,必须相同
 *       2.1.3)引用类型时,小于或等于
 *   2.2)子类方法抛出的异常小于或等于父类的------异常之后
 * 3)一大:
 *   3.1)子类方法的访问权限大于或等于父类的---访问控制修饰符后
 */


//父类大,子类小
class Coo{
	void show(){}
	double say(){return 0.0;}
	Doo sayHi(){return null;}
	public Coo test(){return null;}
}
class Doo extends Coo{
	//int show(){return 1;} //编译错误,void时必须相同
	//int say(){return 0.0;} //编译错误,基本类型时必须相同
	//Coo sayHi(){return null;} //编译错误,引用类型必须小于或等于
	public Doo test(){return null;}
}

以上是继承的使用及相关的一些所完善继承的结构的一些方法,以上内容可能会有出入,部分出自转载,欢迎大家踊跃留言指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值