频道栏目
首页 > 资讯 > 其他 > 正文

编程开发基础知识:继承问题

17-09-06        来源:[db:作者]  
收藏   我要投稿

8继承

8.1什么是继承?

继承是从已有的类中派生出新的类,新的类能够吸收已有的类的属性和方法,并能派生出新的属性和方法。(换种说话,从已有的类中提取共有的属性和方法,把它作为父类,已有的类都继承这个类。)

8.2为什么要使用继承?

使用继承可以优化设计

Dog类

name ,health,love

strain

Print()

 

Penguin类

name ,health,love

Sex

Print()

 

Pet类

name ,health,love

Print()

 

8.3如何实现继承?

1.定义父类

2.子类 extends 父类

 

extends 关键字

[访问修饰符] class pet{

共有的属性 和方法

}

 

[访问修饰符] class Dog extends Pet{

子类特有的属性和方法

}

 

java 只支持单根继承,每个子类只能有一个直接父类,一个父类可以被多个子类继承。

8.4子类访问父类成员

(1)使用super关键字,super代表父类对象 ;

(2)在子类构造方法中调用且必须是第一句。

(3)不可以访问父类中定义为private的属性和方法。

访问父类构造方法

super() 表示调用父类的无参构造

super(name) 表示调用父类的带参构造 super(属性1,属性2,属性3….)

访问父类属性

super.name

访问父类方法

super.print() super.方法名 调用父类的方法

 

调用规则:

子类:没有通过this显示的调用自己的构造方法,也没有super(属性名)调用父类的带参构造方法,那么默认调用父类的无参构造方法。

子类:子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造

子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则

示例:

父类Pet

/**

* 1.将共有的属性,和方法 抽取到父类中

* 2.通过 extends 关键字 让子类继承父类 建立子父类之间的联系

* 构造的调用规则:

* super() 表示调用父类的无参构造 super(属性1,属性2,属性3...) 表示调用父类的带参构造

* 子类中没有通过this(属性名),this()调用自身的其他构造,也没有通过super(属性名)显式的调用父类的带参构造,默认调用父类的无参构造。

* 子类通过super(属性名)调用父类的带参构造方法,那么执行父类的带参构造,而不会执行无参构造

* 子类:子类构造方法通过this显示调用自身的其他构造方法时,在相应构造方法中应用以上两条规则

* super.方法名() 表示调用父类的方法

* @authorAdministrator

*/

publicclassPet {

privateString name; //名字

privateinthealth;//健康值

privateintlove; //亲密度

/**

* 父类里无参构造

*/

publicPet() {

System.out.println("调用了父类Pet中的无参构造Pet()");

}

/**

* 父类里带2个参数 name,health的构造

* @paramname

* @paramhealth

*/

publicPet(String name,inthealth){

super(); //表示Object基类中的无参构造 ,super()写不写都一样,不写默认也会调用

this.name= name;

this.health= health;

System.out.println("调用了父类Pet中带2个参数的构造Pet(name,health)");

}

/**

* 父类Pet的构造中,只能出现super()表示调用基类Object的无参构造 ,this(),this(属性名) 表示调用自身的其他构造 ,不可能出现super(属性名)

* @paramname

* @paramhealth

* @paramlove

*/

publicPet(String name, inthealth, intlove) {

this(name,health);

this.love= love;

}

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name= name;

}

publicintgetHealth() {

returnhealth;

}

publicvoidsetHealth(inthealth) {

this.health= health;

}

publicintgetLove() {

returnlove;

}

publicvoidsetLove(intlove) {

this.love= love;

}

 

publicvoidprint(){

System.out.print("宠物的自白:\n我叫"+this.getName()+",我的健康值是:"+this.getHealth()+",和主人的亲密度为:"+this.getLove());

}

}

子类Dog

/**

* 1如何写子父类之间带参构造

* 2.如何调用父类的方法 super.方法名

* @authorAdministrator

*

*/

publicclassDog extendsPet {

privateString strain; //品种 狗狗特有的属性

/**

* 无参构造

*/

publicDog() {

super();

System.out.println("调用了子类Dog()中的无参构造");

}

/**

* 带2个参数name,strain的构造

* @paramname

* @paramstrain

*/

publicDog(String name,String strain){

super(); //表示显示的调用父类里的无参构造,写不写都一样,默认都会去调用父类的无参构造

//super.方法名 调用父类Pet中set方法给name属性赋值 this.setName(name);

super.setName(name);

this.strain= strain;

System.out.println("调用了子类Dog(name,strain)中带2个参数的构造");

}

/**

* 带3个参数 name,health,strain的构造

* @paramname

* @paramhealth

* @paramstrain

*/

publicDog(String name,inthealth,String strain){

super(name,health); //super(属性名)调用父类里带2个参数的构造

this.strain= strain;

System.out.println("调用了子类Dog(name,health,strain)中带3个参数的构造");

}

/**

* 子类Dog中带4个参数的构造

* @paramname

* @paramhealth

* @paramlove

* @paramstrain

*/

publicDog(String name,inthealth,intlove,String strain){

this(name,health,strain); //调用自身的带3个参数的构造,给name,health,strain3个属性赋值

super.setLove(love);

System.out.println("调用了子类Dog(name,health,love,strain)中带4个参数的构造");

}

publicString getStrain() {

returnstrain;

}

publicvoidsetStrain(String strain) {

this.strain= strain;

}

publicvoidprint(){

//先去调用父类的print()显示前3个属性的信息

super.print();

System.out.println(",我是一只"+this.getStrain());

}

}

子类Penguin:

publicclassPenguin extendsPet {

privateString sex; //性别 企鹅特有的属性

publicPenguin() {

 

}

publicPenguin(String name,inthealth,intlove,String sex) {

/*super.setName(name);

super.setHealth(health);

super.setLove(love);*/

super(name,health,love);

this.sex= sex;

}

publicString getSex() {

returnsex;

}

publicvoidsetSex(String sex) {

this.sex= sex;

}

publicvoidprint(){

super.print();

System.out.println(",我的性别是:"+this.getSex());

}

}

8.5子类继承父类什么?

只能继承public 和protected 修饰的,不管在不在同一包里

继承默认(default)修饰的,只能在同一个包里

构造方法不能继承。只能调用 ,通过super调用。

8.6何时用继承?

is-a 关系的设计使用继承 (猫是一种哺乳动物,藏獒是一种狗)

8.7 重写Override

子类根据需求对父类继承的方法进行重新编写,

重写时,可以用super.方法的方式来保留父类的方法

构造方法不能被重写

方法重写的规则:

方法名相同

参数列表相同

返回值类型相同或者是其子类

访问权限不能严于父类

(如果父类方法用protected修饰 ,子类可以用protected,public ,如果父类用default修饰的,子类可以用default,protected,public)

父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法。

子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法。

父类的私有方法不能被子类覆盖

不能抛出比父类方法更多的异常,运行时异常除外。

面试题: 重写和重载的区别?

方法重写:父子类, 方法同名,同参,返回值相同或是其子类,访问权限不能严于父类的方法权限

方法重载:同一个类 方法同名,参数列表不同(个数,类型,顺序),和返回值,访问权限无关。

示例:

importjava.io.FileNotFoundException;

importjava.text.ParseException;

publicclassBase {

publicvoidceshi1(){

System.out.println("hello");

}

voidceshi2(){

System.out.println("测试2");

}

 

protectedvoidceshi2(String name,String sex){

}

publicintceshi3(inta){

returna;

}

publicBase getBase(){

returnnewBase();

}

/**

* 父类的静态方法

*/

publicstaticvoidceshi4(){

}

/**

* 父类的非静态方法(普通方法)

*/

publicvoidceshi5(){

}

publicstaticvoidceshi6(){

System.out.println("父类Base中的静态方法ceshi6()");

}

privatevoidceshi7(inta){

System.out.println(10);

}

/**

* 该方法抛出2个可查的异常

* @throwsFileNotFoundException

* @throwsParseException

*/

publicvoidceshi8() throwsFileNotFoundException,ParseException{

}

/**

* 该方法抛出2个运行时异常

* @throwsArithmeticException

* @throwsNullPointerException

*/

publicvoidceshi9() throwsArithmeticException,NullPointerException{

 

}

}

importjava.io.FileNotFoundException;

importjava.text.ParseException;

publicclassSub extendsBase {

publicvoidceshi1(){

System.out.println("world");

}

/**

* 编译错误 ,访问权限(访问修饰符级别>=父类的方法的访问级别) 不能严于父类,

*/

/*private void ceshi2(){

System.out.println("子类里的测试2");

}*/

 

protected/*public*/voidceshi2(){

 

}

/**

* 重写,参数列表相同

*/

protectedvoidceshi2(String name,String sex){

 

}

/**

* 重写,返回值类型和父类相同

*/

publicintceshi3(intb){

returnb;

}

/**

* 重写,返回值类型是其子类

*/

publicSub getBase(){

returnnewSub();

}

/**

* 编译错误,不是重写,父类的静态方法不能被子类覆盖为非静态方法

*/

/*public void ceshi4(){

 

}*/

/**

* 编译错误,不是重写 父类的非静态方法不能被子类覆盖为静态方法

*/

/*public static void ceshi5(){

 

}*/

/**

*不是重写, 只是子类定义了父类同名的静态方法

*/

publicstaticvoidceshi6(){

System.out.println("子类Sub中的静态方法ceshi6()");

}

/**

* 不是重写,此处的ceshi7(inta)和父类Base中的私有方法ceshi7(inta),没有任何关系,就是方法同名

* 父类Base中的ceshi7(inta) 该方法的作用域只在类Base中有效,超过该类,任何地方都访问不到

* @parama

*/

publicvoidceshi7(inta){

System.out.println(12);

}

/**

* 不能抛出比父类方法更多的异常

*/

/*public void ceshi8() throws FileNotFoundException,ParseException,ClassNotFoundException{

 

}*/

/**

* 虽然抛出了比父类更多的异常,但是这些异常是运行时异常,所以不会编译出错,仍旧是重写

*/

publicvoidceshi9() throwsArithmeticException,NullPointerException,ClassCastException,ArrayStoreException{

 

}

}

8.8继承下构造方法的执行过程

例题1:

packagecom.njwb.inherit2;

classPerson{

privateString name;

 

publicString getName() {

returnname;

}

publicvoidsetName(String name) {

this.name= name;

}

publicPerson() {

//super(); //调用Object基类的无参构造

System.out.println("execute Person()");

}

 

publicPerson(String name) {

super();

this.name= name;

System.out.println("execute Person(name)");

}

}

/**

* 学生类 继承Person人类

* @authorAdministrator

*

*/

classStudent extendsPerson{

privateString school; //学校

 

publicString getSchool() {

returnschool;

}

 

publicvoidsetSchool(String school) {

this.school= school;

}

publicStudent() {

System.out.println("execute Student()");

}

 

publicStudent(String name,String school) {

super(name);

this.school= school;

System.out.println("execute School(name,school)");

}

}

/**

* 研究生类 继承学生类

* @authorAdministrator

*

*/

classPostGraduate extendsStudent{

privateString guide; //导师

 

publicString getGuide() {

returnguide;

}

 

publicvoidsetGuide(String guide) {

this.guide= guide;

}

publicPostGraduate() {

System.out.println("execute PostGraduate()");

}

 

publicPostGraduate(String name,String school,String guide) {

super(name,school);

this.guide= guide;

System.out.println("executePostGraduate(name,school,guide) ");

}

}

 

@SuppressWarnings("unused")

publicclassTestStudent {

publicstaticvoidmain(String[] args) {

PostGraduate post = newPostGraduate();

System.out.println("---------------------\n");

PostGraduate post2 = newPostGraduate("张三","北京大学","王教授");

}

}

示例2:

父类的实例成员 --à父类的构造---à子类的实例成员----à子类的构造

classFather{

intnum=getNum() ; //实例成员 getNum()虽然是静态方法,但是赋值给num变量,num是实例成员

publicstaticintgetNum(){

System.out.println("1父类Father中的getNum()");

return10;

}

publicFather() {

System.out.println("2父类Father的无参构造");

}

}

 

classSon extendsFather{

intnum2= getNum2(); //实例成员

publicstaticintgetNum2(){

System.out.println("3子类Son中的getNum2()");

return20;

}

publicSon() {

System.out.println("4子类Son无参构造");

}

}

publicclassTest2 {

publicstaticvoidmain(String[] args) {

Son son= newSon();

}

}

注意:加载顺序:启动类(java虚拟机启动时,被标明为启动类的类)的static block 最先加载(父类静态成员,静态代码块----子类静态成员,静态代码块---父类实例成员,代码块-----父类构造函数------子类实例成员,代码块---子类构造函数)

8.9 final修饰属性、方法和类

final 修饰成员变量,则成为实例常量

final修饰类,类不能被继承

final修饰成员方法,则该方法不能被子类重写。

8.10常量类

/**

* 将项目中能够用到的常量都存放在一个类里,这个类叫做常量类

* @authorAdministrator

*

*/

publicclassConstant {

publicfinalString GENDER="男";

publicfinaldoublePI=3.14;

publicfinalintMAX_COUNT=100;

}

8.11作业

网吧管理系统

User用户类,包含用户名、密码等相关属性

UserManager用户管理类,有一个存放用户的数组,数组的每一个元素是一个User类

方法包括添加用户、删除用户、编辑用户、查询所有用户

UserManagerSystem测试类,包含main方法,调用UserManager用户管理类的增删改查。

相关TAG标签
上一篇:九度[1029]-魔咒词典
下一篇:java和c语言变长参数的底层实现区别
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站