正确使用抽象方法
Properly using abstract methods
我无法理解抽象方法的概念以及如何正确使用它们。
基本上,我被指示编写一个带有抽象超类 "Alien" 和 2 个子类 "Martian and Saturner" 的代码,其中 类 存在 invade()方法应该接受外星人攻击的行星名称作为参数,而不是 return 值。
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++;
}
如果你的 invade() 方法应该接受一个行星,那么第一步实际上是实现一个行星类型(读作:class),然后像这样为每个物种实现 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);
}
我认为您正在寻找这样的东西:
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++;
}
}
}
变化是唯一不变的,抽象什么变化。在您的情况下,每个外星人可能有不同的入侵行星的方式,这可能基于外星人所属的家庭、可用资源以及要入侵的行星类型。
Class外星人是超级class,可能不知道行星的类型(未来可能会有更多),因此也可能有许多不同种类的外星人。一个星球上的每个原住民都可能有不同的入侵行为。因此方法 invade() 最好做成 abstract
。
现在正如您所说,它接受要入侵的行星的名称,return 什么都没有。您可以在 Alien.java 中将其定义为抽象
public abstract void invade(String planetName);
所有子class将实施并提供具体实施。
在 driver 代码中,您可以 迭代 并可以使用行星名称调用方法 invade
。
Edit 如果您需要不同的 Strategy 进行入侵,那么我们需要考虑将其抽象化。您可以定义一个抽象 class InvadingStrategy
或者可以有一个接口。
这可以包括与策略相关的方法。一种这样的方法可以像下面这样
public abstract String getStrategyDescription();
您可能有不同的具体 classes(WaterSystemPollutionStrategy
、BombingStrategy
等),它们将提供 InvadingStrategy
定义的抽象方法的实现。现在你对 invade
方法的签名可能像
public abstract void invade(String planetName, InvadingStrategy strategy);
可以根据要入侵的星球名称调用invade
方法,具体攻略objectclass。在 Alien.java 的子 class 方法实现 invade
方法时,您可以打印行星的名称以及由 [=28=104=] 编辑的字符串=].
编辑 2
下面你可以看到 classes 和界面,我尽量保持与你提供的代码相似的结构,但仍然尽量保持代码的灵活性以适应未来的变化。通过遵循良好的 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);
}
外星人的子 class : Martian.java 同样地,你可以拥有外星人的各种子class
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 的具体 class :MissileStrategy 同样,你可以有多种策略
public class MissileStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "shooting missiles at";
}
}
另一个实施 InvadingStrategy 的具体 class:WaterSystemDestructionStrategy
public class WaterSystemDestructionStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "polluting the water systems of";
}
}
Driver代码
导入 java.util.ArrayList;
导入 java.util.Arrays;
导入 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++;
}
}
}
我无法理解抽象方法的概念以及如何正确使用它们。
基本上,我被指示编写一个带有抽象超类 "Alien" 和 2 个子类 "Martian and Saturner" 的代码,其中 类 存在 invade()方法应该接受外星人攻击的行星名称作为参数,而不是 return 值。
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++;
}
如果你的 invade() 方法应该接受一个行星,那么第一步实际上是实现一个行星类型(读作:class),然后像这样为每个物种实现 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);
}
我认为您正在寻找这样的东西:
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++;
}
}
}
变化是唯一不变的,抽象什么变化。在您的情况下,每个外星人可能有不同的入侵行星的方式,这可能基于外星人所属的家庭、可用资源以及要入侵的行星类型。
Class外星人是超级class,可能不知道行星的类型(未来可能会有更多),因此也可能有许多不同种类的外星人。一个星球上的每个原住民都可能有不同的入侵行为。因此方法 invade() 最好做成 abstract
。
现在正如您所说,它接受要入侵的行星的名称,return 什么都没有。您可以在 Alien.java 中将其定义为抽象
public abstract void invade(String planetName);
所有子class将实施并提供具体实施。
在 driver 代码中,您可以 迭代 并可以使用行星名称调用方法 invade
。
Edit 如果您需要不同的 Strategy 进行入侵,那么我们需要考虑将其抽象化。您可以定义一个抽象 class InvadingStrategy
或者可以有一个接口。
这可以包括与策略相关的方法。一种这样的方法可以像下面这样
public abstract String getStrategyDescription();
您可能有不同的具体 classes(WaterSystemPollutionStrategy
、BombingStrategy
等),它们将提供 InvadingStrategy
定义的抽象方法的实现。现在你对 invade
方法的签名可能像
public abstract void invade(String planetName, InvadingStrategy strategy);
可以根据要入侵的星球名称调用invade
方法,具体攻略objectclass。在 Alien.java 的子 class 方法实现 invade
方法时,您可以打印行星的名称以及由 [=28=104=] 编辑的字符串=].
编辑 2
下面你可以看到 classes 和界面,我尽量保持与你提供的代码相似的结构,但仍然尽量保持代码的灵活性以适应未来的变化。通过遵循良好的 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);
}
外星人的子 class : Martian.java 同样地,你可以拥有外星人的各种子class
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 的具体 class :MissileStrategy 同样,你可以有多种策略
public class MissileStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "shooting missiles at";
}
}
另一个实施 InvadingStrategy 的具体 class:WaterSystemDestructionStrategy
public class WaterSystemDestructionStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "polluting the water systems of";
}
}
Driver代码 导入 java.util.ArrayList; 导入 java.util.Arrays; 导入 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++;
}
}
}