Conflict of method call using Interface in Java - java

Yesterday, I had an interview and I was given the following scenario:
There are 3 classes namely Main.java, MobilePhone.java, DeskPhone.java and one Interface ITelephone.java. powerOn() method is implemented in both classes MobilePhone.java and DeskPhone.java.
How can I call powerOn() method in DeskPhone class after creating an instance of MobilePhone class? In other word, how can I print "You are in DeskPhone class" and "You are in MobilePhone class" in last two calls in Main class?
Is there any another way to solve this problem without renaming powerOn() method in either of class?
Main.java
public class Main {
public static void main(String[] args) {
ITelephone timsPhone;
timsPhone = new DeskPhone(123456);
timsPhone.powerOn();
timsPhone = new MobilePhone(45678);
//Question begins here
timsPhone.powerOn();
timsPhone.powerOn();
}
}
ITelephone.java
public interface ITelephone {
void powerOn();
}
MobilePhone.java
public class MobilePhone implements ITelephone{
private int myNumber;
public MobilePhone(int myNumber) {
this.myNumber = myNumber;
}
#Override
public void powerOn() {
System.out.println("You are in MobilePhone class");
}
}
DeskPhone.java
public class DeskPhone implements ITelephone {
private int myNumber;
public DeskPhone(int myNumber) {
this.myNumber = myNumber;
}
#Override
public void powerOn() {
System.out.println("You are in DeskPhone class");
}
}

Assign the MobilePhone object to a different local variable.
In the current code, once the value of the timsPhone variable is replaced by the MobilePhone object, the DeskPhone object is unreachable and you cannot call its powerOn() method.
Suggested code:
ITelephone timsDeskPhone = new DeskPhone(123456);
timsDeskPhone.powerOn();
ITelephone timsMobilePhone = new MobilePhone(45678);
timsMobilePhone.powerOn();
timsDeskPhone.powerOn();
Output
You are in DeskPhone class
You are in MobilePhone class
You are in DeskPhone class

You might try to isolate in a static method the calling to your interface method..
public class Main {
public static void main(String[] args) {
phonePowerOn(new DeskPhone(123456));
phonePowerOn(new MobilePhone(45678));
}
static void phonePowerOn(ITelephone timsPhone){
if (timsPhone != null){
timsPhone.powerOn();
}
}
}

Either you misunderstood the question, it was a trick, or possibly a little of both. Were those first four lines of main given to you like that? Did they tell you that you can't change them? Then the tactful response might be adding a few lines strategically like this:
static void main(String[] args){
ITelephone timsPhone;
timsPhone = new DeskPhone(123456);
timsPhone.powerOn();
ITelephone timsDeskPhone = timsPhone;
timsPhone = new MobilePhone(45678);
ITelephone timsMobilePhone = timsPhone;
timsPhone = timsDeskPhone;
timsPhone.powerOn();
timsPhone = timsMobilePhone;
timsPhone.powerOn();
}
This meets their specifications and shows an understanding of interfaces and references. With a question like this, the code is only of secondary importance. I would think they're really trying to assess communication, response to stress, and maybe even creativity. So just immediately saying, "You can't do that" really isn't much better than one that throws a ClassCastException.
The fun way is to fight fire with fire:
public class MobilePhone implements ITelephone{
private int myNumber;
public MobilePhone(int myNumber) {
this.myNumber = myNumber;
}
private int powerOnCallCount = 0;
#Override
public void powerOn() {
if (powerOnCallCount == 0){
System.out.println("You are in DeskPhone class")
} else {
System.out.println("You are in MobilePhone class");
}
powerOnCallCount++;
}
}
Again, we've only added code, it meets their specifications, and shows the same understanding of interfaces and references.
Or course, a sarcastic answer like this usually won't win points with the interview panel, but has use in the right situation. Remember, they're on trial, too. If I've already tried to gently steer towards a solution like the first and they don't back down, now I'm getting suspicious of their technical knowledge and company culture. If I've noticed a few other yellow flags, then I'd consider something like this to turn the tables. The kind of company I'd want to work for would appreciate that I already tried the tactful approach, met their specifications without compromising technical knowledge, and had enough spine to try my own test on them. I'd probably only resort to it if I was already convinced I didn't want the job, but wanted to give them one last chance to win me over.
Plus, if they practice test driven design, they'd pretty much have to offer me the job right on the spot.

Related

Avoiding switch statements nth time

One argument that is often made concerning avoiding switch statements is that if there is a change/addition, you will have to look all over your code where in your code switch statements are that are effected by a new choice. (and you might forget to change one).
That sounds interesting, but if I use other constructs like function pointers (jump tables) like here:
[https://ultimatecourses.com/blog/deprecating-the-switch-statement-for-object-literals][1]
or here
[https://simpleprogrammer.com/refactoring-switches-to-classes/][1]
I will have the same problem in adapting those when new choices are required.
So.. if I have switches/choices at all, what is the best choice to implement the "Open/Closed principle"?
The only way I see is instead of using
switch(person.position){
case "manager":
break;
case "worker":
break;
case: "temp"
....
is to feed the whole Person object for "John Smith" into a function where then the appropriate functions will be invoked.
The switch statement will be in the class:
class Person {
...
...
public void applyBonus(){
switch (this.position) {
case "manager": this.addBonus(10000)
break;
}
}
If now any changes are requested it's only in the "Person" class.
Do I get this right?
I answered a similar question earlier today (but in C#). Your Person could be abstract and force classes that implement the Person class to define it's bonus amount. Then your base class could simply implement a applyBonus. For example:
public abstract class Person
{
protected double salary, bonusAmount, baseSalary;
protected Person(double baseSalary, double bonusAmount)
{
this.baseSalary = baseSalary;
this.bonusAmount = bonusAmount;
}
public void applyBonus()
{
salary += bonusAmount;
}
}
public final class Manager extends Person {
public Manager()
{
super(100000.0, 1000.0);
}
}
public final class Worker extends Person {
public Worker()
{
super(10000.0, 500.0);
}
}
public final class TempWorker extends Person {
public TempWorker()
{
super(1000.0, 200.0);
}
}
Now you can do things like:
var myTeam = new Person[] { new Manager(), new Worker(), new Worker(), new TempWorker() };
// apply bonuses:
for(var member : myTeam){
member.applyBonus();
}
Now, I'm not saying this is how you should do this, by any means. I am showing you how polymorphism and other OOP patterns can help you think more abstractly about the objects in your program and avoid iterating through types.

World of Zuul: non-static method getCurrentRoom() cannot be referenced from a static context

I know this question comes up often, but even after looking at asked question's I can't find a solution..
So for school we have to create an own version of World of Zuul. I've implemented a beamer in it. First I put it in the Game class, but I decided it would be better to have it in it's own class, Beamer. The Beamer class looks as follows:
public class Beamer
{
private Room beamerRoom;
private Room beamer;
private int timesFired;
private boolean beamerCharged;
public Beamer(int timesFired, boolean beamerCharged)
{
this.timesFired = 0;
this.beamerCharged = false;
}
public int getTimesFired()
{
return timesFired;
}
public Room getBeamerRoom()
{
return beamerRoom;
}
public boolean getBeamerCharged()
{
return beamerCharged;
}
public Room setBeamerRoom(Room room)
{
this.beamerRoom = Game.getCurrentRoom();
return beamerRoom;
}
/**
* Try to use beamer device. When you charge the beamer, it memorizes the current room.
* When you fire the beamer, it transports you immediately back to the room it was
* charged in.
*/
public void beamer(Command command){
if (!command.hasSecondWord()) {
// if there is no second word, we don't know what to do...
System.out.println("Charge or fire beamer?");
return;
}
String action = command.getSecondWord();
if (action.equals("charge")) {
if(timesFired() < 1)
{
beamerRoom = Game.getCurrentRoom();
System.out.println("This room is charged to beam!");
beamerCharged = true;
}
else
{
System.out.println("The beamer has already been fired and can't be charged again");
}
} else if (action.equals("fire")) {
if(beamerCharged == true)
{
if(timesFired < 1)
{
Game.getCurrentRoom() = beamer.getBeamerRoom();
System.out.println("The beamer has succesfully been fired!");
System.out.println(currentRoom.getLongDescription());
timesFired++;
beamerCharged = false;
}
else
{
System.out.println("You can only fire the beamer once!");
}
}
else
{
System.out.println("The beamer hasn't been charged yet!");
}
} else {
System.out.println("Invalid beamer command!");
return;
}
}
}
I get the error method getCurrentRoom() cannot be referenced from a static context here:
beamerRoom = Game.getCurrentRoom();
The method in Game to get the current room is as follows:
public Room getCurrentRoom()
{
return currentRoom;
}
Very simple, which in my mind should work.
How can I solve this issue? I've looked around but can't find a fix that works..
If you need more of the Game class code, please ask. I didn't post it here since it's 300+ lines.
EDIT:
I already found what I did wrong. By using Game.getCurrentRoom it looked at the class Game, rather than an object of the Game. At least that's what I think went wrong. I had the error message with more methods, using capital letters (Game.<method>), Player.<method>), but when I didn't use the capital letters (game.<method>), player.<method>) it worked fine.
So I guess the problem is solved.
When you call Game.getCurrentRoom() you arer trying to call the method on the class Game. But you defined the method as an instance method. So you either need to change your code to use a singleton instane of Game to access its instance methods, or you need to declare the mehtods on Class as static. Note that those methods again can only access class members, not instance members.
public static Room getCurrentRoom()
{
return currentRoom; // currentRoom has to be declared as a private static class member
}

Java Object Oriented - Advanced Constructors Assistance ? :\

Can someone please check my code and determine why my pickup function's not working.
-- write missing methods for these procedures to occur
Dog bob = new Dog(5);
System.out.println(bob);
bob.walk();
bob.walk();
bob.pickUp("Tennis ball");
System.out.println(bob);
bob.drop();
bob.bark();
System.out.println(bob);
-- In my class where I've defined the pickUp method:
public Head()
{
}
public void pickUp(String object)
{
this.object = object;
System.out.println("Picked up "+object);
}
public String getObject()
{
return object;
}
public void drop()
{
System.out.println("Dropped "+object);
object = null;
}
public void bark()
{
System.out.println("WOOF!");
}
public String toString()
{
return "Head is holding "+ object;
}
}
-- The other class where I'm utilising the method:
public class Dog
{
private int position;
private Leg hind1;
private Leg hind2;
private Leg front1;
private Leg front2;
private Head head = new Head();
//Constructor for Dog class
public Dog(int position)
{
hind1 = new Leg(position-2);
hind2 = new Leg(position-2);
front1 = new Leg(position+2);
front2 = new Leg(position+2);
}
public void walk()
{
front1.step();
front2.step();
hind1.step();
hind2.step();
System.out.println("Pitter patter...");
}
public String toString()
{
return "Head is holding " + head+", Leg at "+hind1.position+", Leg at "+ hind2.position+", Leg at "+front1.position+", Leg at "+front2.position;
}
public void pickup()
{
head.pickUp(head.object);
}
public void drop()
{
head.drop();
}
public void bark()
{
head.bark();
}
PS. head is a new object I've made which belongs to the Head Class, Which is where the first code is from. I'm currently trying to get the second code working to display a picked up object that head picked up.
-EDIT : Even if I do put a string in(Eg. head.pickUp("ball");), it still displays "cannot find symbol - method.pickUp(java.lang.String)" when I try running the procedures.
EDITED (a third time!): Now that you've posted your code, I've confirmed that my answer below is correct. Tl;dr - you're trying to use head.object before it's been set. What you should be passing in to pickUp is a string that represents the name of the object you want to pick up. For example, head.pickUp("ball");
It would help if you could clarify a bit more what you mean by "not working" - however, it looks like you've got a sort of chicken-and-egg problem here:
If I'm reading this right, your code looks something like this? (Including the entire class in your comment might help)
public class Head {
String object;
public void pickUp(String object)
{
this.object = object;
System.out.println("Picked up "+object);
}
}
public class SomeOtherClass {
Head head = new Head();
public void pickup()
{
head.pickUp(head.object);
}
}
EDITED (again) for clarity - It looks like you're trying to use the pickup function (the one in SomeOtherClass) to define the object property of your head. However, by calling it with head.object, you assume that head.object is already defined. Where are you actually setting the string you want to use?
It's not really clear what you're trying to accomplish here - but you might want to try either 1) setting head.object in a constructor in your head class. or 2) calling head.pickUp with a string other than head.object (which hasn't been set yet). - Try replacing head.object with "Hello World", for starters. Or, if I've totally misunderstood your intent, perhaps give us a bit more context?
EDITED - because I realized that your pickup function wasn't in Head.

Java-How do I call a class with a string?

I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.

Java - Creating an array of methods

I'm designing a text-based adventure game for a school progress. I have each "level" set up as a class, and each explorable area (node) as a method within the appropriate class.
What's messing with me is the code to move from one node to another. Because each node is connected to up to four other nodes, I have to repeat an extremely similar block of code in each method.
What I'd prefer to do is include an array of methods at the beginning of each node, like this:
public static void zero()
{
... adjacentNodes[] = {one(), two(), three(), four()};
}
And then send that array to a generic method, and have it send the player to the right node:
public static void move(...[] adjacentNodes, int index)
{
adjacentNodes[index];
}
I simplified my code, but that's the general idea. Is this possible?
Whenever you think of pointer-to-function, you translate to Java by using the Adapter pattern (or a variation). It would be something like this:
public class Node {
...
public void goNorth() { ... }
public void goSouth() { ... }
public void goEast() { ... }
public void goWest() { ... }
interface MoveAction {
void move();
}
private MoveAction[] moveActions = new MoveAction[] {
new MoveAction() { public void move() { goNorth(); } },
new MoveAction() { public void move() { goSouth(); } },
new MoveAction() { public void move() { goEast(); } },
new MoveAction() { public void move() { goWest(); } },
};
public void move(int index) {
moveActions[index].move();
}
}
Just have your nodes be objects that all adhere to the same interface, then you'll be able to call their methods reliably.
Since Java does not have the concept of methods as first-class entities, this is only possible using reflection, which is painful and error-prone.
The best approximation would probably be to have the levels as enums with a per-instance implementation of a method:
public enum Level1 implements Explorable{
ROOM1 {
public void explore() {
// fight monster
}
}, ROOM2 {
public void explore() {
// solve riddle
}
}, ROOM3 {
public void explore() {
// rescue maiden
}
};
}
public interface Explorable{
public abstract void explore();
}
public static void move(Explorable[] adjacentNodes, int index)
{
adjacentNodes[index].explore();
}
However, this is a bit of an abuse of the enum concept. I wouldn't use it for a serious project.
Your design has fundamental flaws. Normal OO design would have each "level" be an object (of Class 'level' or something like it). each 'explorable area' would also be an object, contained within the level object - maybe of class ExplorableArea. The 'explorable areas' can be different kinds, in which case you make them different subclasses of ExplorableArea.
Try thinking about solutions without reflection. It's can be enums, for example.
I arrive late at the party with one possible approach, now you can use java.util.function (link) for this kind of problem.
To literally answer the question, regardless of its correctness, or applicability, here a possible version:
public static void zero()
{
Function<World, World> one = (World start) -> RoomWithMonster.in(start);
Function<World, World> two = (World start) -> EmptyRoom.in(start);
Function<World, World> three = (World start) -> RoomWithMonster.in(start);
Function<World, World> four = (World start) -> Treasure.in(start);
List<Function<World, World>> adjacentNodes = List.of(one, two, three, four);
return adjacentNodes;
}
public static void move(List<Function<World, World>> possibleNodes, int index)
{
World beginning = World.start();
World end = possibleNodes.get(index).apply(beginning);
}
This approach prefer immutability and add a little World class to abstract away the state of the game but still maintaining the question you wanted.
NB: fortunately now the reflection comments are obsolete!
You can use Reflection class to create an array of methods.
http://java.sun.com/developer/technicalArticles/ALT/Reflection/

Categories