2017-04-15 90 views
0

我很难理解抽象方法的概念以及如何正确使用它们。正确使用抽象方法

基本上,我被指示编写一个抽象超类“外星人”和2个子类“火星人和星期六”的代码,在这些类中存在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++; 
    } 

回答

1

的变化是不变,摘要什么样的变化的唯一的事情。在你的情况下,每个外星人可能有不同的入侵行星的方式,这种行星可能基于外星人所属的家族,可用资源以及基于行星类型入侵的行星。

类外国人是超一流的,可能不知道的行星的(将来可能会有更多),因此还可能有许多种diffenert外星人。每个行星的本地人可能有不同的入侵行为。因此方法侵入()最好是作为abstract制成。

现在,当你说接受这个星球的名称侵入并返回什么。您可以在Alien.java中将其定义为摘要

public abstract void invade(String planetName); 

所有子类都将实现并提供具体实现。

在驱动代码中,您可以迭代,并且可以调用具有星球名称的方法invade

编辑如果你需要不同的战略为入侵然后再次,我们需要考虑使得它作为抽象的。您可以定义一个抽象类InvadingStrategy或可以有一个接口。 这可以包括与策略相关的方法。一种这样的methid可以像下面

public abstract String getStrategyDescription(); 

您可以有不同的具体类(WaterSystemPollutionStrategyBombingStrategy等),这将提供的由InvadingStrategy定义的抽象方法的实现。现在,您的invade方法签名可以像

public abstract void invade(String planetName, InvadingStrategy strategy); 

可以调用invade方法按照这个星球的名字入侵和具体策略类的对象。在invade方法由Alien.java的子类的实现,你可以打印由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); 
} 

子类外国人的:Martian.java喜欢聪明人,你可以有外国人

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接口的各个子类:这可以包括该策略的必要方法。目前只有一种方法来获得战略的描述。

public interface InvadingStrategy { 
    String getStrategyDescription(); 
} 

具体类实现InvadingStrategy:MissileStrategy喜欢聪明人,你可以有不同的策略

public class MissileStrategy implements InvadingStrategy { 

    @Override 
    public String getStrategyDescription() { 
     return "shooting missiles at"; 
    } 

} 

一个更具体的类实现InvadingStrategy:WaterSystemDestructionStrategy

public class WaterSystemDestructionStrategy implements InvadingStrategy { 

    @Override 
    public String getStrategyDescription() { 
     return "polluting the water systems of"; 
    } 

} 

驱动代码 进口的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++; 
     } 
    } 
} 
+0

对于简单情况,您可以使用字符串,但是从良好的灵活设计角度来看,您必须将策略相关行为封装在单独的类中。你将来可能有不同的策略。我再次编辑了我的答案,希望这会有所帮助。 –

+0

你可以看看我编辑的代码在原来的帖子和评估它,我添加策略的入侵方法,并添加了一些东西到ArrayList的驱动程序 –

+0

@KelOkekpe你可以很好地起诉简单的字符串,但正如我所说将不会灵活的设计来适应未来的变化,我编辑了我的答案,并包括我所说的结构。希望它会有所帮助。欢呼和快乐的学习。 –

0

如果你的入侵()方法应该接受一个星球,第一步是实际执行行星式(阅读:类),然后实现了每一个物种这样的入侵方法:

@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); 
} 
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++; 
     } 
    } 
} 
+0

这有助于很多,但我没有在我的原始文章中包含的是入侵方法不仅应该获得行星的价值,而且也应该入侵的方法。因此,而不是输出是的“我是火星人入侵”或“我是一个Saturner入侵:”每次,它应该有所不同,从(即)我在:,是一个火星拍摄的导弹或我是一个Saturner污染水系统: –

+0

@Kel Okekpe,您也可以参考我的回答,希望这将有助于你在抽象的概念,多一点理解。欢呼和快乐学习 –

+0

我已将此添加到入侵方法 公共无效入侵(字符串planetName,字符串invadeMethod){ 的System.out.println(“我是一个Saturner” + invadeMethod + planetName); 这到ArrayList: 列表方法= Arrays.asList(新的String [] { “在射击导弹”, “污染的水系统”, “燃烧”, “泛滥”}); 这是正确的? –