稍复杂的成员变量类型
- 类作为成员变量
- 接口作为成员变量
类作为成员变量
如常见的定义成员变量:String str=“哈哈哈”,实际上String就是一个类,只不过是JDK作者写的。同样,我们也可以自定义一个类当作成员变量。
比如在游戏中,英雄是一个类,在设定英雄类的成员变量的时候,我们想给英雄配备一把武器。问题是其他英雄也要有武器,而且武器有很多参数,因此我们把武器也创建成一个类,武器类给不同的英雄类当成员变量使用,详见下例:
public class Hero {
private String name; // 英雄名
private int age;
private Weapon weapon;
public Hero() {
}
public Hero(String name, int age, Weapon weapon) {
this.name = name;
this.age = age;
this.weapon = weapon;
}
public void attack() {
System.out.println("年龄为" + age + "岁的" + name +
"正在用" + weapon.getWeaponCode() + "攻击敌方!");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Weapon getWeapon() {
return weapon;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
}
public class Weapon {
private String weaponCode;// 武器代号
public Weapon() {
}
public Weapon(String weaponCode) {
this.weaponCode = weaponCode;
}
public String getWeaponCode() {
return weaponCode;
}
public void setWeaponCode(String weaponCode) {
this.weaponCode = weaponCode;
}
}
public class Demo {
public static void main(String[] args) {
Hero hero = new Hero();
hero.setName("老亚瑟");
hero.setAge(98);
Weapon weapon = new Weapon("大宝剑");
hero.setWeapon(weapon);
hero.attack();
}
}
// 年龄为98的老亚瑟正在用大宝剑攻击敌方!
接口作为成员变量
接口同样可以作为类的成员变量
// 这是新定义的接口:Skill
public interface Skill {
void use();
}
以上面的英雄例子为基础做一些添加:
- 加入一个成员变量:技能Skill,这是一个接口类型
- 在英雄的方法attack()中,加入关于技能的调用 skill.use()
- 对全参构造方法、getter/setter做相应调整
public class Hero {
private String name; // 英雄名
private int age;
private Weapon weapon;
private Skill skill;// 英雄的技能
public Hero() {
}
public Hero(String name, int age, Weapon weapon, Skill skill) {
this.name = name;
this.age = age;
this.weapon = weapon;
this.skill = skill;
}
public void attack() {
System.out.print("年龄为" + age + "岁的" + name +
"正在用" + weapon.getWeaponCode() + "攻击敌方并使用了技能:");
skill.use(); // 调用接口中的抽象方法
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public Weapon getWeapon() {
return weapon;
}
public Skill getSkill() {
return skill;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setWeapon(Weapon weapon) {
this.weapon = weapon;
}
public void setSkill(Skill skill) {
this.skill = skill;
}
}
public class Demo {
public static void main(String[] args) {
Hero hero = new Hero();
hero.setName("[老亚瑟]");
hero.setAge(98);
Weapon weapon = new Weapon("[大宝剑]");
hero.setWeapon(weapon);
hero.setSkill(new SkillImpl());// 写法1:使用单独定义的实现类,SkillImpl为此而生
hero.attack();
Skill skill2 = new Skill() {// 写法2:使用匿名内部类
@Override
public void use() {
System.out.println("[回旋打击]");
}
};
hero.setSkill(skill2);
hero.attack();
hero.setSkill(new Skill() {// 写法3:使用匿名内部类、匿名对象
@Override
public void use() {
System.out.println("[誓约之盾]");
}
});
hero.attack();
}
}
/*
年龄为98岁的[老亚瑟]正在用[大宝剑]攻击敌方并使用了技能:[圣剑裁决]
年龄为98岁的[老亚瑟]正在用[大宝剑]攻击敌方并使用了技能:[回旋打击]
年龄为98岁的[老亚瑟]正在用[大宝剑]攻击敌方并使用了技能:[誓约之盾]
*/
对于上面的写法1,由于没有使用匿名内部类,因此需要创建一个实现类SkillImpl如下:
public class SkillImpl implements Skill {
@Override
public void use() {
System.out.println("[圣剑裁决]");
}
}
上面的代码块作为实现类,即对接口中use()方法的一个简单重写。main方法中就可以用本实现类new出一个对象(本例中这一步实际上也是匿名对象),用Setter把这个对象传入到Hero类中,Hero的成员变量skill就得到了该实现类的对象,在attack()中调用SkillImpl中的use()方法输出了[圣剑裁决]。变量为接口,传入的却是实现类对象,相当于Skill skill=new SkillImpl,接口类型skill指向的是该接口的实现类,因此发生了向上转型。