Reputation:
I am having trouble grasping the concept of abstract methods and how to properly use them.
Basically, I am being instructed to write a code with an abstract superclass "Alien" and 2 subclasses "Martian and Saturner", within these classes exists the invade() method which should accept the name of a planet for the alien to attack as an argument and does not return a value.
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++;
}
Upvotes: 0
Views: 110
Reputation: 5336
Change is the only thing that is constant, Abstract what changes. In your case each alien may have a different way of invading a planet which may be based upon the family to which an alien belongs, resources available and also based upon the type of planet to invade.
Class Alien being the super class, may not be aware of the types of Planets (In future there may be many more) and hence there may also be many diffenert kinds of aliens. Each native of a planet may have differnet invading behavior. Hence method invade() is best made as abstract
.
Now as you said it accepts the Name of the planet to invade and return nothing. You can define it in Alien.java as abstract
public abstract void invade(String planetName);
All the subclasses will implement and provide the concrete implementation.
In the driver code you may iterate and can invoke the method invade
with the name of a planet.
Edit In case you need different Strategy for invading then again we need to think of making it as abstract. You may define an abstract class InvadingStrategy
or can have an interface.
This can include the methids related to strategy. One such methid can be like below
public abstract String getStrategyDescription();
You may have different concrete classes (WaterSystemPollutionStrategy
, BombingStrategy
, etc) which will provide the implementation of the abstract methods defined by InvadingStrategy
. Now your signature for invade
method may be like
public abstract void invade(String planetName, InvadingStrategy strategy);
You can invoke the invade
method as per the planet name to invade and the object of concrete strategy class. In the implementation of invade
methods by the subclasses of Alien.java you may print the name of the planet passed along with the String as returned by the getStrategyDescription()
.
Edit 2
Below you can see the classes and interface, I have tried to keep the structure similar as of the code you provided, but still tried to keep the code flexible to accommodate the future changes. By following good OOPs principles you write clean code which is easy to maintain and understand.
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);
}
Sub class of Alien : Martian.java Like wise you can have various subclasses of 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 : This can include the necessary emthods for the strategy. Currently just haing one method to get the description of the strategy.
public interface InvadingStrategy {
String getStrategyDescription();
}
Concrete class implementing the InvadingStrategy : MissileStrategy Like wise you can have various strategies
public class MissileStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "shooting missiles at";
}
}
One more Concrete class implementing the InvadingStrategy : WaterSystemDestructionStrategy
public class WaterSystemDestructionStrategy implements InvadingStrategy {
@Override
public String getStrategyDescription() {
return "polluting the water systems of";
}
}
Driver code 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++;
}
}
}
Upvotes: 1
Reputation:
If your invade() method should accept a planet, the first step is actually implementing a planet type (read: class) and then implement the invade method for every species like this:
@Override
void invade(Planet target) {
//attack planet
}
For attacking different planets you would need a list of available planets, iterate over aliens, pick a random planet from the planet list (check out java.util.Random) and call the invade method on each alien:
Random rng = new Random();
for (Alien alien : aliens) {
int roll = rng.nextInt(aliens.size());
Planet target = planets.get(roll);
alien.invade(target);
}
Upvotes: 0
Reputation: 1927
I think that you are looking for something like this:
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++;
}
}
}
Upvotes: 1