我无法理解抽象方法的概念以及如何正确使用它们。
基本上,我被指示编写一个带有抽象超类“Alien”和2个子类“Martian and Saturner”的代码,在这些类中存在invade()方法,它应该接受外星人的行星名称。攻击作为参数并且不返回值。
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
abstract class Alien
{
private String planet;
private String age;
private String name;
private String skinColor;
private String alienPower;
public Alien(String planet, String age, String name, String skinColor, String alienPower)
{
this.planet=planet;
this.age=age;
this.name=name;
this.skinColor=skinColor;
this.alienPower=alienPower;
}
public abstract void invade(String planetName);
public String toString()
{
return name + " is from " + planet + ", is " + age + " years old, " + " has " + skinColor + " skin, and has the ability " + alienPower ;
}
}
class Martian extends Alien {
public Martian(String p, String a, String n, String s, String ap) {
super(p,a,n,s,ap);
}
@Override
public void invade(String strategy, String planetName) {
System.out.println("I am a Martian " + strategy + planetName);
}
}
class Saturner extends Alien {
public Saturner(String p, String a, String n, String s, String ap) {
super(p,a,n,s,ap);
}
public void invade(String strategy, String planetName) {
System.out.println("I am a Saturner " + strategy + planetName);
}
}
public class TestAlien {
public static void main(String[]args) {
ArrayList<Alien> alienList = new ArrayList<>();
List<String> planets = Arrays.asList(new String[] {"Earth", "June", "Mercury", "Venus", "Neptune"});
List<String> methods = Arrays.asList(new String[] {"shooting missiles at", "polluting the water systems of", "burning", "flooding"});
alienList.add(new Martian("Mars", "148", "Zornok", "red", "Read minds"));
alienList.add(new Saturner("Saturn", "89", "Hookman", "pitch black ", "Go invisible"));
alienList.add(new Martian("Mars", "18", "Guthrax", "gray", "Teleport"));
alienList.add(new Saturner("Saturn", "300", "Lamron", "blue", "Fly\n"));
int i = 0;
for (Alien al : alienList) {
System.out.println("Alien race: " + al.getClass().getName() + " || description = " + al.toString());
al.invade(methods.get(i) al.invade(planets.get(i));
i++;
}
答案 0 :(得分:1)
我认为你正在寻找这样的东西:
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
abstract class Alien {
private String p;
private String a;
private String n;
private String s;
private String ap;
public Alien(String p, String a, String n, String s, String ap) {
this.p = p;
this.a = a;
this.n = n;
this.s = s;
this.ap = ap;
}
public abstract void invade(String planetName);
}
class Martian extends Alien {
public Martian(String p, String a, String n, String s, String ap) {
super(p,a,n,s,ap);
}
@Override
public void invade(String planetName) {
System.out.println("I am a Martian invading " + planetName);
}
}
class Saturner extends Alien {
public Saturner(String p, String a, String n, String s, String ap) {
super(p,a,n,s,ap);
}
public void invade(String planetName) {
System.out.println("I am a Saturner invading " + planetName);
}
}
public class TestAlien {
public static void main(String[]args) {
ArrayList<Alien> alienList = new ArrayList<>();
List<String> planets = Arrays.asList(new String[] {"Earth", "June", "Mercury", "Venus", "Neptune"});
alienList.add(new Martian("Mars", "148", "Zornok", "red", "Read minds"));
alienList.add(new Saturner("Saturn", "89", "Hookman", "pitch black ", "Go invisible"));
alienList.add(new Martian("Mars", "18", "Guthrax", "gray", "Teleport"));
alienList.add(new Saturner("Saturn", "300", "Lamron", "blue", "Fly\n"));
int i = 0;
for (Alien al : alienList) {
System.out.println("Alien race: " + al.getClass().getName() + " || description = " + al.toString());
al.invade(planets.get(i));
i++;
}
}
}
答案 1 :(得分:1)
变化是唯一不变的,抽象变更。在你的情况下,每个外星人可能有不同的入侵行星的方式,这可能是基于外星人所属的家庭,可用资源以及入侵的行星类型。
等级外星人是超级阶级,可能不知道行星的类型(将来可能会有更多),因此也可能有许多不同类型的外星人。行星的每个本地人可能具有不同的入侵行为。因此,方法 invade()最好是 abstract
。
现在正如你所说它接受行星的名字入侵并且什么都不返回。您可以在Alien.java中将其定义为抽象
public abstract void invade(String planetName);
所有子类都将实现并提供具体实现。
在驱动程序代码中,您可以迭代并可以使用行星名称调用方法invade
。
编辑如果你需要不同的策略进行入侵,那么我们需要考虑将其作为抽象。您可以定义抽象类InvadingStrategy
或可以具有接口。
这可以包括与策略相关的方法。一个这样的方法可以如下所示
public abstract String getStrategyDescription();
您可能有不同的具体类(WaterSystemPollutionStrategy
,BombingStrategy
等),它们将提供InvadingStrategy
定义的抽象方法的实现。现在,invade
方法的签名可能就像
public abstract void invade(String planetName, InvadingStrategy strategy);
您可以根据要侵略的行星名称和具体策略类的对象调用invade
方法。在Alien.java的子类实现invade
方法时,您可以打印与getStrategyDescription()
返回的字符串一起传递的行星名称。
修改2
下面你可以看到类和接口,我试图保持与你提供的代码类似的结构,但仍然试图保持代码的灵活性以适应未来的变化。通过遵循良好的OOP原则,您可以编写易于维护和理解的简洁代码。
<强> Alien.java 强>
public abstract class Alien {
// Copying it from the question, Suggestion : USE contextual meaningful names
public Alien(String p, String a, String n, String s, String ap) {
// set the properties and do the necessary initialization.
}
public abstract void invade(String planetName, InvadingStrategy strategy);
}
Alien的子类:Martian.java 同样聪明的你可以拥有Alien的各种子类
public class Martian extends Alien {
public Martian(String p, String a, String n, String s, String ap) {
super(p, a, n, s, ap);
}
@Override
public void invade(String planetName, InvadingStrategy strategy) {
System.out.println("I am Martian, I am going to invade " + planetName + " and My Strategy will be "
+ strategy.getStrategyDescription());
}
}
InvadingStrategy Interface :这可以包含策略的必要方法。目前只是采用一种方法来获得战略的描述。
public interface InvadingStrategy {
String getStrategyDescription();
}
实施InvadingStrategy的具体类:MissileStrategy 同样你可以有各种策略
public class MissileStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "shooting missiles at";
}
}
另一个实现InvadingStrategy的Concrete类:WaterSystemDestructionStrategy
public class WaterSystemDestructionStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "polluting the water systems of";
}
}
驱动程序代码 import java.util.ArrayList; import java.util.Arrays; import java.util.List;
public class Driver {
public static void main(String[] args) {
ArrayList<Alien> alienList = new ArrayList<>();
alienList.add(new Martian("Mars", "148", "Zornok", "red", "Read minds"));
alienList.add(new Saturner("Saturn", "89", "Hookman", "pitch black ", "Go invisible"));
alienList.add(new Martian("Mars", "18", "Guthrax", "gray", "Teleport"));
alienList.add(new Saturner("Saturn", "300", "Lamron", "blue", "Fly\n"));
List<String> planets = Arrays.asList(new String[] {"Earth", "June", "Mercury", "Venus", "Neptune"});
List<InvadingStrategy> methods = Arrays.asList(new InvadingStrategy[]{new MissileStrategy(),new WaterSystemDestructionStrategy(),new BurningStrategy(),new FloodingStrategy()});
int i = 0;
for(Alien alien : alienList){
alien.invade(planets.get(i) , methods.get(i));
i++;
}
}
}
答案 2 :(得分:0)
如果你的invade()方法应该接受一个行星,第一步实际上是实现一个行星类型(读取:类),然后为每个物种实现这样的入侵方法:
@Override
void invade(Planet target) {
//attack planet
}
对于攻击不同的行星,您需要一个可用行星列表,迭代外星人,从行星列表中选择一个随机行星(查看java.util.Random)并为每个外星人调用入侵方法:
Random rng = new Random();
for (Alien alien : aliens) {
int roll = rng.nextInt(aliens.size());
Planet target = planets.get(roll);
alien.invade(target);
}