Java-类与类之间的关系

本文深入解析Java中的继承概念,包括代码格式、子类访问父类成员、特点、方法重写与内存模型,以及this与super的用法。通过实例展示如何创建对象并理解构造方法调用顺序。同时涵盖了关联与依赖关系在面向对象设计中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承

继承的概述

继承是面向对象三大特征中的核心特征,是实现代码复用的重要方式,是类与类之间的一种关系。父类抽取了共性的内容,子类可以在父类的基础上进行拓展新的属性和行为。
:所有的类都直接或者间接Object

继承的代码格式

继承使用extends关键字
格式

class 子类 extends 父类{
}
//动物类
public class Animal {
    private String name;
    private int age;
    public Animal(String name, int age) { this.name = name;this.age = age; }
    public Animal() { }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public void eat(){
        System.out.println(this.getName()+"吃东西");
    }
}
//老虎类,继承了动物类
public class Tiger extends Animal {
    public Tiger(String name, int age) { super(name, age);}
    public Tiger() {}
    public void hunting(){ System.out.println(this.getName()+"在捕猎"); }
}
//测试类
public class Test {
    public static void main(String[] args) {
        Tiger t = new Tiger("东北虎",1);
        t.hunting();
        t.eat();
    }
}

在这里插入图片描述
从上类案例中可以看出,发生了继承关系之后,子类汇会继承父类中除构造方法和静态方法,静态变量之外的东西,并且可以调用非private修饰的内容和定义新的内容。

子类访问父类成员的方法

在父类中,被private修饰的成员需要提供公开的get和set放法,子类可以通过继承来的这些方法对属性进行访问。
:属性是可以被继承的,继承发生后,子类对继承来的属性拥有自己的内存空间。

继承的特点

1、Java只支持单继承
2、Java支持多层继承
3、父类定义了继承树中共性内容,子类定义了该类个性内容。
4、在结合多态后,能使用父类时尽量使用父类,提高程序扩展性。

方法重写与继承内存图解

方法重写的概念与格式

子类继承父类后,可以继承父类中非private修饰的方法,若子类发现父类提供的某一个方法不够用的时候,可以自己通过重写来实现属于自己的逻辑,这样,当子类对象再次调用方法的时候,调用的就是重写后的方法。
格式:
​ 定义一个与父类方法声明完全相同的方法,方法体重写
子类在重写父类中的方法时,需要在方法的上一行加上@Override注解,表明这是重写父类中的方法。
发生继承关系后创建对象的内存图:
在这里插入图片描述

方法重写注意事项

1、方法重写发生在继承关系中
2、重写的方法,方法名要相同
3、参数列表要相同
4、返回值类型:基本数据类型要一致,引用数据类型:子类<=父类
5、权限:子类>=父类
6、抛出异常:子类<=父类

继承后创建对象构造方法的调用顺序

public class Animal {
    private String name;
    private int age;
    public Animal(String name, int age) { this.name = name;this.age = age; }
    public Animal() {
        System.out.println("这是父类的无惨构造方法");
    }
}
public class Tiger extends Animal {
    public Tiger(String name, int age) { super(name, age);}
    public Tiger() {
        System.out.println("这是子类的无参构造方法");
    }
}
public class Test {
    public static void main(String[] args) {
       Tiger t = new Tiger();
    }
}
/**
 * 这是父类的无惨构造方法
 * 这是子类的无参构造方法
 */

通过上述案例可以看出,发生继承后,当创建子类对象的时候,系统均会先初始化父类的内容,在初始化子类本身。目的在于子类对象中包含了其对应的父类存储空间,便可以包含了其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。
代码体现在子类的构造方法调用时,一定先调用父类的构造方法。

this与super

调用普通成员:
this.成员变量 可以访问本类对象的成员变量
super.成员变量 可以访问父类的成员变量
this.成员方法() 可以访问本类对象的成员方法
super.成员方法() 可以访问父类的成员方法

子类方法中
​ 访问子类自身的成员用this.
​ 访问父类的成员super.

就近原则:
​ 局部 > 本类成员 > 父类成员

super 关键字

  • 1.调用执行父类的成员,但是super并不是父类的对象
  • 2.默认提供super(),调用执行父类中的无参构造方法
  • super(name, age); 调用执行父类中的有参构造方法
  • super()默认存在在子类构造方法的第一行
  • 3.super调用父类的成员方法,调用父类的成员变量

this

  • 1.当前正在创建的对象,当前正在使用的对象
  • 2.this() 调用本类中无参的构造方法
  • this(name,age) 调用本类中有参的构造方法 ,但是两者不能互相调用
  • 3.this调用本类的成员方法,调用本类的成员变量

关联和依赖关系

继承:is-a
关联:has-a
依赖:use-a

关联关系的概述

当在类A中需要使用到类B的某些方法时,可以将类B作为类A的成员,从而产生关联

/**  
* @ClassName: Pet  
* @Description: Pet宠物类
*    
* 宠物姓名,宠物颜色,宠物种类三个成员变量
*/

public class Pet {
	/**  
	* @Fields name : 宠物姓名  
	*/  
	private String name;
	/**  
	* @Fields color : 宠物颜色  
	*/  
	private String color;
	/**  
	* @Fields kind : 宠物种类  
	*/  
	private String kind;

	/**  
	* @Title: Pet      
	*/
	public Pet() {
	}

	/**  
	* @Title: Pet  
	* @param name
	* @param color
	* @param kind    
	*/
	public Pet(String name, String color, String kind) {
		this.name = name;
		this.color = color;
        this.kind = kind;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the color
	 */
	public String getColor() {
		return color;
	}

	/**
	 * @param color the color to set
	 */
	public void setColor(String color) {
		this.color = color;
	}

	/**
	 * @return the kind
	 */
	public String getKind() {
		return kind;
	}

	/**
	 * @param kind the kind to set
	 */
	public void setKind(String kind) {
		this.kind = kind;
	}
}
/**  
* @ClassName: Person  
* @Description: Person类
*    
* 姓名,年龄,宠物三个成员变量
* 有showInfo(显示信息)的方法
* 
* 当Pet作为Person的成员变量时,两个数据类型的关系为关联
*/

public class Person {

	/**  
	* @Fields name : 姓名  
	*/  
	private String name;
	/**  
	* @Fields age : 年龄  
	*/  
	private int age;
	
	/**  
	* @Fields pet : 宠物  
	*/  
	private Pet pet;

	/**  
	* @Title: Person      
	*/
	public Person() {
	}

	/**  
	* @Title: Person  
	* @param name
	* @param age    
	* @param pet
	*/
	public Person(String name, int age, Pet pet) {
		this.name = name;
		this.age = age;
		this.pet = pet;
	}

	/**  
	* @Title: showInfo  
	* @Description: 显示个人信息      
	*/
	public void showInfo() {
		System.out.println("我的名字是:" + this.name + ",我的年龄是:" + this.age);
		System.out.println("我的宠物是"+pet.getColor()+"色的"+pet.getKind()+",它叫"+pet.getName());
	}

}

依赖关系的概述

指一个类A中的某个方法需要使用到另一个类B。依赖关系的特性:这种关系是具有偶然性的、临时性的、非常弱的,但是类B的变化会影响到类A。
表现形式:B作为A的某个方法的形式参数
案例:
游戏需求:
1、定义一个英雄类Hero,可以通过这个类创建英雄角色
属性:
游戏角色拥有昵称name,等级level,血量blood,攻击力power,防御力defence,种族kind,
装备Equip(只能装3个装备,初始没有装备)。
方法:
游戏角色拥有基本攻击方法(拥有一定几率打出暴击)attack(Monster m),死亡判定方法isDead(),添加装备的方法addEquip(Equip e),获取角色信息的方法show()。
2、定义一个怪兽类Monster,可以通过这个类创建怪兽角色
属性:
怪兽拥有名称name,等级level,血量blood,攻击力power,防御力defence,种族kind。
方法:
怪兽拥有基本攻击方法attack(Hero h),死亡判定方法isDead(),获取怪兽信息的方法show()。
3、定义装备类Equip,可以通过这个类创建各种装备
属性:
装备拥有名称name,级别level,颜色color,类别kind,攻击力power,防御力defence。
方法:
装备拥有获取装备信息的方法show()。
4、测试类
创建一个游戏角色:英雄类Hero、装备Equip、怪兽Monster,英雄类Hero装上装备,双方使用回合制的形式进行攻击(一人打一下,角色英雄类Hero先攻击,失血量=攻击-防御 ,攻击<防御,不产生攻击),直到一方死亡,游戏结束。
其中:
暴击>某个值
失血量=(攻击+暴击)-防御

package com.cautious.xin.game;

/**
 * @Description 角色类
 * @Author Cautious-Xin
 * @Date 2020/10/29 14:38
 */
public abstract class Role {
    private String name;
    private int level;
    private int blood;
    private int attack;
    private int defence;
    private String kind;
    public Role() { }
    public Role(String name, int level, int blood, int attack, int defence, String kind) {
        this.name = name;
        this.level = level;
        this.blood = blood;
        this.attack = attack;
        this.defence = defence;
        this.kind = kind;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getLevel() {
        return level;
    }
    public void setLevel(int level) {
        this.level = level;
    }
    public int getBlood() {
        return blood;
    }
    public void setBlood(int blood) {
        this.blood = blood;
    }
    public int getAttack() {
        return attack;
    }
    public void setAttack(int attack) {
        this.attack = attack;
    }
    public int getDefence() {
        return defence;
    }
    public void setDefence(int defence) {
        this.defence = defence;
    }
    public String getKind() {
        return kind;
    }
    public void setKind(String kind) {
        this.kind = kind;
    }
    public void show(){
        System.out.println("昵称:"+this.getName()+" 等级:"+this.getLevel()+" 血量:"+this.getBlood()+" 攻击力:"
                +this.getAttack()+" 防御力:"+this.getDefence()+" 种族:"+this.getKind());
    }
    public abstract void  attack(Role role);
    public boolean isDead(){
        if(this.getBlood()<=0){
            return false;
        }
        return true;
    }
}

package com.cautious.xin.game;

/**
 * @Description 怪兽类
 * @Author Cautious-Xin
 * @Date 2020/10/29 14:57
 */
public class Monster extends Role{
    public Monster() { }
    public Monster(String name, int level, int blood, int attack, int defence, String kind) {
        super(name, level, blood, attack, defence, kind); }
    @Override
    public void attack(Role role) {
        if(this.getAttack()>=role.getDefence()){//攻击大于防御,计算失血量
            int loseBlood = this.getAttack()-role.getDefence();//计算出本次攻击对方损失了多少血
            int hasBlood = role.getBlood()-loseBlood;//计算对方在遭受攻击后还剩余多少血
            //更新血量
            role.setBlood(hasBlood);
            System.out.println("怪兽"+this.getName()+"攻击力英雄"+role.getName()+",使得英雄损失了"+loseBlood+"的血量");
        }else {
            System.out.println("怪兽此次攻击无效");
        }
    }
}
package com.cautious.xin.game;

/**
 * @Description 英雄类
 * @Author Cautious-Xin
 * @Date 2020/10/29 14:43
 */
public class Hero extends Role{
    private Equip []equip = new Equip[3];
    int index = 0;
    public void addEquip(Equip e){
        if(equip[index]==null&&index<equip.length){
            equip[index++]=e;
            //计算加上装备的防御力和攻击力
            int attack = this.getAttack()+e.getAttack();
            this.setAttack(attack);
            int defance = this.getDefence()+e.getDefence();
            this.setDefence(defance);
            /*this.setAttack(this.getAttack()+e.getAttack());*/

        }
    }
    
    @Override
    public void attack(Role role) {//英雄的攻击方法
        int attack = this.getAttack();//获取当前攻击力
        int critRate = (int) (Math.random()*10+1);//暴击率
        if(critRate>5){
            attack+=10*critRate;//说明产生了暴击
        }
        if(attack>=role.getDefence()){
            int loseBlood = attack-role.getDefence();//计算出本次攻击对方损失了多少血
            int hasBlood = role.getBlood()-loseBlood;//计算对方在遭受攻击后还剩余多少血
            //更新血量
            role.setBlood(hasBlood);
            System.out.println("英雄"+this.getName()+"攻击了怪兽"+role.getName()+",使得怪兽损失了"+loseBlood+"的血量");
        }else {
            System.out.println("英雄此次攻击无效");
        }
    }

    public Hero() {
    }

    public Hero(String name, int level, int blood, int attack, int defence, String kind, Equip[] equip) {
        super(name, level, blood, attack, defence, kind);
        this.equip = equip;
    }

    public Equip[] getEquip() {
        return equip;
    }

    public void setEquip(Equip[] equip) {
        this.equip = equip;
    }

    @Override
    public void show() {
        super.show();
        if(this.getEquip()!=null) {
            System.out.println(this.getName() + "的装备有:");
            for (Equip equip1 : equip) {
                if(equip1!=null) {
                    equip1.show();
                }
            }
        }
    }
}
package com.cautious.xin.game;

/**
 * @Description 装备类
 * @Author Cautious-Xin
 * @Date 2020/10/29 14:44
 */
public class Equip {
    private String name;
    private int level;
    private String color;
    private String kind;
    private int attack;
    private int defence;

    public Equip(String name, int level, String color, String kind, int attack, int defence) {
        this.name = name;
        this.level = level;
        this.color = color;
        this.kind = kind;
        this.attack = attack;
        this.defence = defence;
    }

    public Equip() {
    }

    public String getName() {
        return name;
    }

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

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getKind() {
        return kind;
    }

    public void setKind(String kind) {
        this.kind = kind;
    }

    public int getAttack() {
        return attack;
    }

    public void setAttack(int attack) {
        this.attack = attack;
    }

    public int getDefence() {
        return defence;
    }

    public void setDefence(int defence) {
        this.defence = defence;
    }

    public void show(){
        System.out.println("装备名称:"+name+" 级别:"+level+" 颜色:"+color+" 类别:"+kind+" 攻击力:"+attack+" 防御力:"+defence);
    }
}

package com.cautious.xin.game;

/**
 * @Description TODO
 * @Author Cautious-Xin
 * @Date 2020/10/29 15:19
 */
public class GameTest {
    public static void main(String[] args) throws InterruptedException {
        Role h =  new Hero("迪迦",45,500,90,40,"奥特曼",new Equip[3]);
        Equip e = new Equip("屠龙宝刀",40,"银色","刀",10,5);
        System.out.println("添加装备前:");
         h.show();
         if(h instanceof Hero){
             Hero h1 = (Hero) h;
             h1.addEquip(e);
         }

        System.out.println("添加装备后:");
        h.show();
        System.out.println();


        Role m = new Monster("哥斯拉",45,550,120,60,"怪兽");
        while (true){
            h.attack(m);
            if(!m.isDead()){
                System.out.println("怪兽死了");
                break;
            }
            Thread.sleep(1000);
            m.attack(h);
            if(!h.isDead()){
                System.out.println("英雄死了");
                break;
            }
            Thread.sleep(1000);
            System.out.println("此回合结束,双方的信息如下");
            h.show();
            m.show();
            System.out.println("-------------------------------");
        }
    }

}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值