I'm having trouble calling move.m_north from another function.
It is asking me to make the class move and the function m_north static, but if I do i can't reference y unless I make it static too.
I found that if y is static then any dot object I make will have the same value for y, and I need multiple dots
public class dot {
int y=0; //<-- 3. but if I make this static then it will stay the same for every object
public void step(int direction) {
switch (direction){
case 0:
move.m_north(); //<-- 1. is asking to make move.m_north static
}
}
public class move {
public int m_north() {
if (y > 0) {
y -= 1; //<-- 2. but I need to modify and read non static variables
return -1;
} else return -2;
}
}
}
I am able to call m_north if it is not in the move class but there are many similar functions which I believe need to be split up so I can use same names and it becomes easier to find different functions.
I would much appreciate any assistance.
You can make this work by declaring an instance of the move class. For example (with captialization changed to match Java naming conventions):
public class Dot {
int y=0;
Move move = new Move();
public void step(int direction) {
switch (direction){
case 0:
move.m_north();
}
}
public class Move {
public int m_north() {
if (y > 0) {
y -= 1;
return -1;
} else return -2;
}
}
}
Note that Move with an uppercase M is the class name, and move with a lowercase m is the name of an instance variable in the class Dot.
The reason this is required is that m_north requires an enclosing instance of Dot in order to access its y field. To put it another way, you need to call m_north on a specific dot's move instance. Making the method static doesn't provide an enclosing dot in scope.
Related
I have a unit(soldier) class which contains a getAttackBonus() method and a getResistBonus() method. These must return different values for every time a soldier either attacks or is attacked.
To be specific, getResistBonus() can for example start at 8 but for every time the soldier is attacked, it will decrease by 2 until it reaches a certain value (for example 2 as a final resist bonus) where it will no longer decrease. How would I go about doing this?
Currently I am using in my method which does not work when I attempt to test it as a JUnit class, it keeps giving me 6 as the integer:
public int getResistBonus() {
int resist = 8;
while(resist != 2) {
return resist -= 2;
}
return 2;
}
You need to change a bit your code.
First you need to define resist at instance level, not method level.
Second it is better to use an if instead of a while because you are not making a loop, but only checking a single condition.
So the code can be something similar to that:
public class YourClass {
// Define resist at instance level
private int resist = 8;
....
public int getResistBonus() {
// Replace the while with an if
if (resist > 2) {
resist -= 2;
}
return resist;
}
}
i'm quite new to Java so let me know if I'm missing something basic here..
I came across this chunk of code referencing a method from the same class. (i.e. both methods exist with the same superclass)
//Method (Part of a bigger superclass)
private int hopDistance()
{//Implementation Not Shown}
//The Code in Question with the function call
public boolean simulate()
{
int position = 0;
for (int count = 0; count < maxHops; count++)
{
position += hopDistance();
if (position >= goalDistance)
{
return true;
}
else if (position < 0)
{
return false;
}
}
return false;
}
Why does it seem that line 7 in the code on the bottom is referencing the hopDistance() class without instantiating an object? I understand how static methods can have this property but didn't understand how non-static ones could...
In Java, one method within a class can call other methods within the same instance of that class without explicitly invoking the class name.
In other words, if simulate() and hopDistance() are both defined as methods in the same class, then
public boolean simulate() {
hopDistance();
}
and
public boolean simulate() {
this.hopDistance();
}
are identical.
START OF INSTRUCTIONS
If there is a game piece on the clicked square (clickedSquare.getPiece()!= null)
Make sure the game piece belongs to the current player. You can get the owning player by calling the getPlayerType() method on the AbstractGamePiece returned by getPiece(). You can then compare that to the currentPlayerTurn JailBreak class member.
If the piece on the clicked square belongs to the current player
Set the selected square equal to the clicked square
Call the select() method on the selected square to show the yellow border
END OF INSTRUCTIONS
I've figured out how to highlight the piece by implementing the select() method, butt
I've tried several different implementations, such as AbstractGamePiece.getPlayerType()==currentPlayerTurn, using nested if statements to set conditions on clickedSquare.getPiece(), and a couple others that I can't think of off the top. I can't seem to get a reference to getPlayerType() from the abstract class. There is pre-written code in the class that seems to work fine as far as accessing the AbstractGamePiece, such as
private void changePlayerTurn()
{
if (currentPlayerTurn == AbstractGamePiece.PLAYER_OUTLAWS)
currentPlayerTurn = AbstractGamePiece.PLAYER_POSSE;
else
currentPlayerTurn = AbstractGamePiece.PLAYER_OUTLAWS;
}
I feel like I'm going about this wrong, but I can't seem to get a reference to the getPlayerType(). The one time I did, I created a new object of the abstract class, but the constructor needs 3 parameters that aren't really appropriate here.
Supporting code:
abstract public class AbstractGamePiece
{
// All class members are provided as part of the activity starter!
// These two constants define the Outlaws and Posse teams
static public final int PLAYER_OUTLAWS = 0;
static public final int PLAYER_POSSE = 1;
// These variables hold the piece's column and row index
protected int myCol;
protected int myRow;
// This variable indicates which team the piece belongs to
protected int myPlayerType;
// These two strings contain the piece's full name and first letter abbreviation
private String myAbbreviation;
private String myName;
// All derived classes will need to implement this method
abstract public boolean hasEscaped();
// The student should complete this constructor by initializing the member
// variables with the provided data.
public AbstractGamePiece(String name, String abbreviation, int playerType)
{
myName = name;
myAbbreviation = abbreviation;
myPlayerType = playerType;
}
public int getPlayerType()
{
return myPlayerType;
}
public void setPosition (int row, int col)
{
myRow = row;
myCol = col;
}
public int getRow()
{
return myRow;
}
public int getCol()
{
return myCol;
}
public String getAbbreviation()
{
return myAbbreviation;
}
public String toString()
{
return (myName + " at " + "(" + myRow + "," + myCol + ")");
}
public boolean canMoveToLocation(List<GameSquare> path)
{
return false;
}
public boolean isCaptured(GameBoard gameBoard)
{
return false;
}
Code that highlights the pieces indiscriminately has been implemented successfully.
private void handleClickedSquare(GameSquare clickedSquare)
{
if (selectedSquare == null)
{
selectedSquare=clickedSquare;
selectedSquare.select();
}
else if (selectedSquare == clickedSquare)
{
selectedSquare.deselect();
selectedSquare = null;
}
else
{
}
Why is it that I'm unable to create a reference to the getPlayerType() method?
Just call getPlayerType on any expression of type X, where X is either AbstractGamePiece or any subclass thereof. For example, square.getPiece().getPlayerType().
Method references are a thing in java and are definitely not what you want, you're using words ('I'm unable to create a reference to getPlayerType') that mean something else. A method reference looks like AbstractGamePiece::getPlayerType, and let you ship the concept of invoking that method around to other code (for example, you could make a method that calls some code 10 times in a row - so this method takes, as argument, 'some code' - and method references are a way to that). It is not what you want here, you want to just invoke that method. Which is done with ref.getPlayerType() where ref is an expression whose type is compatible with AbstractGamePiece. From context, clickedSquare.getPiece() is that expression.
I've seen many code-parts in mostly old(java mostly) projects that look like
if(type == typeOne){
callFunctionOne();
}else if (type == typeTwo){
callFunctionTwo();
}else if (type == typeThree){
callFunctionThree();
}//i've seen over ~800 lines like this!
where "type" could be an enum or really anything and the whole thing could be written in switch/case style too.
My question is: is there a "better"(more stylish/shorter/more readable) way to achieve this?
I've seen constructs in PHP like:
//where $type = "one","two" etc.
$functionName = 'callFunction' . $type;
new $functionName();
But im not sure if this is realy the "better" way and if its even possible in other Languages.
The more interesting question imo is what exactly you want to achieve by this?
Java is an object-oriented language. Therefore i would solve this by one subclass per type:
abstract class Type{
abstract void method();
}
class Type1 extends Type{
void method(){
//do sth. specific for this type
}
}
If the methods are actually all in the same class you could still call them out of these classes by simply passing yourself (i see that this could get ugly).
class RandomClass(){
void method1(){
//do sth for type1
}
void method2(){
//do sth for type2
}
}
abstract class Type{
RandomClass randomClass;
Type(RandomClass randomClass){
this.randomClass = randomClass;
}
abstract void method();
}
class Type1 extends Type{
void method(){
randomClass.method1();
}
}
class Type2 extends Type{
void method(){
randomClass.method2();
}
}
Otherwise you could use reflection, like suggested by Sohaib (example taken from his suggested link):
Yyyy.class.getMethod("methodName").invoke(someArgs)
But using Reflection for somehting like this seems very unhandy as it is inperformant and a nice trap for later maintenance (just imagine someone starts renaming the methods).
So to answer the question itself (at least how i understand it):
Dynamically calling methods e.g. by determining their name dynamically at runtime, is something you only do in scripting languages.
The object-oriented approach might come with overhead, but at the end is the better style for this kind of language.
If both solutions do not work for you, a switch statement or if-else cascade is your best alternative.
As noted in a comment, there are ways to use java's reflection capabilities. See this question for how to do that. That said, reflection is pretty bad style in java and should only be used if you really have no other option. Java's really big on OO-style programming and static type checking and using reflection is skimping on both of those focuses. In doing so you'll likely make your code just as complicated and way harder to debug.
Without reflection, there's not much better you can do if the code block in question happens exactly once. You'd have to implement the logic somewhere, probably involving the same if-else/switch block. However, if you find yourself copy-pasting that same if-elseif-elseif-elseif.... block in multiple places, you can do a bit better.
If type is an enum, you can move the logic to the enum itself, which is really nice from an OO standpoint. Consider the following:
public enum Direction {
NORTH,
SOUTH,
EAST,
WEST
}
public class Foo {
public void bar(Direction d) {
//At some point we want some logic to depend on the vector dx,dy form of d
int dx = 0;
int dy = 0;
switch(d) {
case NORTH:
dy = -1;
break;
case SOUTH:
dy = 1;
break;
case EAST:
dx = 1;
break;
case WEST:
dx = -1;
break;
}
//Use the values in dx, dy
}
}
It's clearly a bad idea to copy-paste this block around your project. If you ever add a new direction, you'd have to return to every such block to add the correct addition. From an OO standpoint, the dx, dy fields are truly part of the enum value, and should be a part of it to begin with. Thus we can change the above to the following:
public enum Direction {
NORTH,
SOUTH,
EAST,
WEST;
public int getDX() {
switch(this) {
case WEST: return -1;
case EAST: return 1;
default: return 0;
}
}
public int getDY() {
switch(this) {
case NORTH: return -1;
case SOUTH: return 1;
default: return 0;
}
}
}
Or, (IMO) even better, represent them as a field
public enum Direction {
NORTH(0,-1),
SOUTH(0,1),
EAST(1,0),
WEST(-1,0);
private int dx;
private int dy;
private Direction(int dx, int dy) {
this.dx = dx;
this.dy = dy;
}
public int getDX() {
return dx;
}
public int getDY() {
return dy;
}
}
From there we can simply use these methods directly in Foo.bar() and don't need any logic:
public class Foo {
public void bar(Direction d) {
//can directly use d.getDX() and d.getDY()
}
}
Your question about function calling is the same, if one level removed. We can either add the switch straight to the enum:
public enum Type {
VALUE_ONE, VALUE_TWO, ...
public void callFunc() {
switch(this) {
case VALUE_ONE:
callFunctionOne();
return;
case VALUE_TWO:
callFunctionTwo();
return;
//....
}
}
}
And then just use it by directly referencing that function:
Type t = //....
t.callFunc();
You could even use some java-8 stuff to represent the function-to-call as a field
#FunctionalInterface
public interface Unit {
public void apply();
}
public enum Type {
VALUE_ONE(Foo::baz),
VALUE_TWO(Foo::baz2),
//...
private Unit funcToCall;
private Type(Unit u) {
this.funcToCall = u;
}
public void callFunc() {
funcToCall.apply();
}
}
If type is not an enum, you can use some (but not all) of the above options. You can still lump your switch logic into a helper method/class and pass control over to it instead of copy/pasting. The more that type is supposed to represent something, and the more you find yourself wanting to switch over it, the more likely an enum is the correct choice.
I'm having a problem with my Java assignment on inheritance. I won't go into detail on the task as that's not my issue. In the program. have a superclass with some fields in it. Two of these fields are ints, xCoord and yCoord. There is then a subclass that obviously also has these ints. It also has another attribute, short direction, that is not contained in the superclass. I need to access all three of these attributes in the user class. The user class needs to be able to change these values. When attempting to compile. I get the error:
error: ';' expected
in all the lines in my user class that try to increment xCoord or yCoord. For example:
mov1.yCoord++
^
So, I don't really know what the problem is. I assume it has something to do with the attributes not be directly declared in that class. My reasoning for this is because I have lines that deal with the short direction in the same manner. For example:
mov1.direction = 1
This goes through the compiler with no problem. So I reckon in must be because xCoord and yCoord only declared in the super class. But that's just my assumption, I could be wrong. Regardless if whether I am or not, I need to fix this while still using inheritance for these fields, the assignment requires it. Any help?
For reference, here are some snippets of relevant code:
The superclass: (didn't include the methods because not relevant)
public class StationaryThing {
// Attributes
protected String name;
protected final int gridlength = 10;
protected final int gridwidth = 10;
public int xCoord;
public int yCoord;
// Constructor
public StationaryThing(String name, int xCoord, int yCoord) {
this.name = name;
this.xCoord = xCoord;
this.yCoord = yCoord;
}
The subclass: (again, didn't include methods)
public class MovingThing extends StationaryThing {
// Attributes
public short direction = 0;
// Constructor
public MovingThing(String name, int xCoord, int yCoord) {
super(name, xCoord, yCoord);
}
And some of the relevant lines from the user class:
for (int i = 0; i < noMoves; i++) {
if (mov1.direction == 0) {
if (hole1.xCoord == mov1.xCoord && hole1.yCoord == mov1.yCoord+1) {
mov1.direction = 1;
mov1.holeAhead();
mov1.directionChange();
}
if (mov1.yCoord == 9) {
mov1.direction = 1;
mov1.directionchange();
}
else {
mov1.displayAttributes
mov1.yCoord++;
}
}
Again, thanks for any help you can give.
Are those lines "missing ;" inside a method? There cannot be "just code" inside the class, but there should be a method like
public void doSth () {
a++;
}
Please refer java code is showing error. ( ';',expected) for a similar situation.