Is there a different way to write get methods in Java? - java

I know that we can retrieve a variable's value by simply writing get methods and return var;. However, is there another way to write a get method to return information on the fields instead? If so, how does one access it. For example, if I have a planeNumber and I want to check it against another object's planeNumber, is there a way to use a boolean to check instead of writing public int getPlaneNumber()?

Seems like you are wanting to implement the Comparable interface? https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
That is it looks like you have an attribute, planeNumber, that you want to use to compare the classes?
Maybe you want something like this
import java.util.Comparator;
import java.util.Objects;
public class Airplane implements Comparable<Airplane> {
private final int planeNumber;
public Airplane(final int planeNumber) {
this.planeNumber = planeNumber;
}
public final int getPlaneNumber() {
return planeNumber;
}
#Override
public int compareTo(final Airplane o) {
return Objects.compare(this, o, Comparator.comparing(Airplane::getPlaneNumber));
}
public static void main(final String... args) {
System.out.println(new Airplane(1).compareTo(new Airplane(2)));
System.out.println(new Airplane(100).compareTo(new Airplane(100)));
System.out.println(new Airplane(1000).compareTo(new Airplane(100)));
}
}
-1
0
1

You could add a method comparing the field values to your class like this (omitting null check in the methods):
class Scratch {
public static void main(String[] args) {
ObjectWithPlaneNumber o1 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o2 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o3 = new ObjectWithPlaneNumber(11);
System.out.println(o1.hasSamePlaneNumber(o2));
System.out.println(o1.hasSamePlaneNumber(o3));
}
static class ObjectWithPlaneNumber {
private final int planeNumber;
public ObjectWithPlaneNumber(int planeNumber) {
this.planeNumber = planeNumber;
}
public boolean hasSamePlaneNumber(ObjectWithPlaneNumber other) {
return this.planeNumber == other.planeNumber;
}
}
}

Related

Question on diamond operator for design pattern strategy

Small question regarding the diamond operator and design pattern strategy for Java, please.
I would like to implement a very specific requirement:
there are some objects to store (in my example called MyThingToStore)
and the requirement is to store them with different kinds of data structures, for comparison.
Therefore, I went to try with a strategy pattern, where each of the strategies is a different way to store, I think this pattern is quite lovely.
The code is as follows:
public class MyThingToStore {
private final String name;
public MyThingToStore(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyThingToStore that = (MyThingToStore) o;
return Objects.equals(name, that.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
#Override
public String toString() {
return "MyThingToStore{" +
"name='" + name + '\'' +
'}';
}
}
public class MyStorage {
private final StorageStrategy storageStrategy;
public MyStorage(StorageStrategy storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
public interface StorageStrategy {
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy{
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And this is working fine, very happy, especially tackled the requirement "easy to change the data structure to do the actual store".
(By the way, side question, if there is an even better way to do this, please let me know!)
Now, looking online at different implementations of strategy patterns, I see this diamond operator which I am having a hard time understanding:
MyThingToStore stays the same.
public class MyStorage {
private final StorageStrategy<MyThingToStore> storageStrategy; //note the diamond here
public MyStorage(StorageStrategy<MyThingToStore> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(MyThingToStore myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
#Override
public String toString() {
return "MyStorage{" +
"storageStrategy=" + storageStrategy +
'}';
}
}
public interface StorageStrategy<MyThingToStore> {
//note the diamond, and it will be colored differently in IDEs
void addToStore(MyThingToStore myThingToStore);
int getSize();
}
public class StorageUsingArrayListStrategy implements StorageStrategy<MyThingToStore> {
private final List<MyThingToStore> storeUsingArrayList = new ArrayList<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingArrayList.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingArrayList.size();
}
}
public class StorageUsingHashSetStrategy implements StorageStrategy<MyThingToStore> {
private final Set<MyThingToStore> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(MyThingToStore myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
public class Main {
public static void main(String[] args) {
final StorageStrategy<MyThingToStore> storageStrategy = new StorageUsingArrayListStrategy();
final MyStorage myStorage = new MyStorage(storageStrategy);
myStorage.addToStore(new MyThingToStore("firstItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
myStorage.addToStore(new MyThingToStore("duplicatedSecondItem"));
System.out.println(myStorage.getSize()); //changing strategy will return a different size, working!
}
}
And both versions will yield the same good result, also be able to answer requirements.
My question is: what are the differences between the version without a diamond operator, and the version with the diamond operator, please?
Which of the two ways are "better" and why?
While this question might appear to be "too vague", I believe there is a reason for a better choice.
I think the confusion comes from how you named type parameter for StorageStrategy in your 2nd example.
Let's name it T for type instead. T in this case is just a placeholder to express what type of objects your StorageStrategy can work with.
public interface StorageStrategy<T> {
void addToStore(T myThingToStore);
int getSize();
}
E.g.
StorageStrategy<MyThingToStore> strategy1 = // Initialization
StorageStrategy<String> strategy2 = // Initialization
strategy1.addToStore(new MyThingToStore("Apple"));
// This works fine, because strategy2 accepts "String" instead of "MyThingToStore"
strategy2.addToStore("Apple");
// Last line doesn't work, because strategy1 can only handle objects of type "MyThingToStore"
strategy1.addToStore("Apple");
To make it work properly, you need to change your different StorageStrategy implementations to also include the type parameter.
public class StorageUsingHashSetStrategy<T> implements StorageStrategy<T> {
private final Set<T> storeUsingHashSet = new HashSet<>();
#Override
public void addToStore(T myThingToStore) {
storeUsingHashSet.add(myThingToStore);
}
#Override
public int getSize() {
return storeUsingHashSet.size();
}
}
And lastly you also want to have a type paremeter for MyStorage
public class MyStorage<T> {
private final StorageStrategy<T> storageStrategy;
public MyStorage(StorageStrategy<T> storageStrategy) {
this.storageStrategy = storageStrategy;
}
public void addToStore(T myThingToStore) {
storageStrategy.addToStore(myThingToStore);
}
public int getSize() {
return storageStrategy.getSize();
}
}
Now you can create a MyStorage and can use it to store essentially any object into it and not just MyThingToStore. Whether that is something you want or not is up to you.
In the second code sample in the declaration of the interface StorageStrategy<MyThingToStore>, MyThingToStore is a Type Variable.
I.e. it's not the actual type, only a placeholder for a type, like T. The common convention is to use single-letter generic type variables (T, U, R, etc.), otherwise it might look confusing like in this case.
Note that in the class declarations, like:
public class StorageUsingArrayListStrategy
implements StorageStrategy<MyThingToStore>
MyThingToStore is no longer a type variable, but the name of the class MyThingToStore because in this case parameterized interface is implemented by a non-parameterized class (i.e. the actual type known to the compile is expected to be provided).

Iterate through inherited classes and call their static methods

I want to iterate through some classes, that inherit from the same superclass.
They all have the same static method, but how can I call it?
I tried it like this, but that does not work:
public abstract class Tower {
private static int text = 5;
public static int getText() {
return text;
}
}
public class aTower extends Tower {
private static int text = 10;
public static int getText() {
return text;
}
}
public class Main {
public static void main(String [] args) {
LinkedList<Class<?extends Tower>> towers = new LinkedList<>();
towers.add(aTower.class);
for (int i = 0; i < towers.size(); i++) {
towers.get(i).getText(); //Does not work
}
}
}
Context
I want to have a list of classes that inherit from Tower for calling static methods of them, for getting e.g. their texture. Is there any other way to do that?
Edit: The main goal is, that I will have many different Towerclasses in a list, and there should be a menu with every towerclass. To paint the menu, I want to get for example the texture, the name, etc. When you click on the menu entry, then you should get an object of the specific tower and you can build it somewhere. But I do not like the idea of having a list of more or less unused instances, and therefore I thought having a static method is the right solution.
Check out Java Interfaces though as already stated they wouldn't be static methods.
public interface ITower {
public String getText();
}
from this point you define your tower objects that implement ITower and then inside main:
public class Main {
public static void main(String [] args) {
List<ITower> towers = new LinkedList<>();
// create your tower objects and add them to the list
towers.add(new ATower());
towers.add(new BTower());
for (ITower iObj : towers) {
iObj.getText();
}
}
}
By converting your static method to an instance method, and using a static field within each subclass, you can get this to work:
public abstract class Tower {
private static int text = 5;
public int getText() {
return text;
}
}
and
public class aTower extends Tower {
private static int text = 10;
#Override public int getText() {
return text;
}
}
and
public class Main {
public static void main(String [] args) {
LinkedList<aTower> towers = new LinkedList<>();
towers.add(new aTower());
for (int i = 0; i < towers.size(); i++) {
towers.get(i).getText();
}
}
}
In your original main() method, you created a List instance for Class objects. I think you had really intended for this to contain aTower instances. This is important because class Class will not have a getText() method.
Polymorphism doesn't work with static methods. Why do you want getText() to be static?
If you have a no-arg constructor in Tower you can use reflection to create an instance from a class name.
Class<Tower> towerClass = (Class<Tower>) Class.forName(classString);
Tower tower = towerClass.newInstance();
tower.staticMethod();

Why couldn't I deal with argument in java?

I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}

How to refer to the value of an object from the method defined - Java

So I have a method as outlined below:
public interface Definitions{
public boolean isEmpty();
}
public class Methods implements Definitions{
public boolean isEmpty{
//Insert code here
}
public static void main(String[] args){
return;
}
}
This method does not take parameters/arguments when it is executed, it just has to return a boolean variable defining whether or not the original object that used it is empty or not, e.g.
public class NewClass{
public static void main(String[] args){
Methods newObject = new Methods();
return newObject.isEmpty();
}
How would I define the method "isEmpty" in order to return a true or false value? My main problem is handling / retrieving the value of the object that uses it. Thanks in advance
One thing I forgot to mention in the question is, the class Methods implements an interface. I have fixed it above. Sorry for the confusion.
might be a good idea to be able to set the state of "empty":
public class Methods implements Definitions {
private boolean empty = true;
public boolean isEmpty() {
return empty;
}
public void setEmpty(boolean empty) {
this.empty = empty;
}
public void checkIsEmpty(ObjectTypeWhichCanBeEmpty obj) {
setEmpty(obj.amIEmpty());
}
Now the million dollar question is what you're trying to do? Why not store the "empty" property in the object you want to check whether it was empty or not?
You should have some class members that are actually the state of the object, for example:
public class Methods{
private boolean empty = true;
public boolean isEmpty() {
return empty;
}
//Then, you can add some method that set the empty field:
public void fillObject() {
empty = false;
}
public void emptyObject() {
empty = true;
}
}

Equals override for String and Int

I have a list in that list I created an object. By using the contains() method, I want to check whether the object already exists or not. For that, I override the equals() method. Everything is perfect upto this. But when I try to do the same thing for String and int the equals() override doesn't not work. Why is it like this? I just posted some sample code for reference.
public class Test
{
private int x;
public Test(int n)
{
x = n;
}
public boolean equals(Object o)
{
return false;
}
public static void main(String[] args)
{
List<Test> list = new ArrayList<Test>();
list.add(new Test(3));
System.out.println("Test Contains Object : " + list.contains(new Test(3))); // Prints always false (Equals override)
List<String> list1 = new ArrayList<String>();
list1.add("Testing");
String a = "Testing";
System.out.println("List1 Contains String : " + list1.contains(a)); // Prints true (Equals override not working)
}
}
String and Integer are both final classes, so you cannot subclass them. Therefore you cannot override their equals methods.
You can, however, subclass ArrayList and create your own contains implementation builds on the existing one.
There is no need for overriding the equals method of Integer or String as they are already implemented and work well.
However, if you want to do it anyways, this would be one way of doing it (Delegation Pattern):
public class MyString {
private String myString;
#Override
public boolean equals(Object o)
return false;
}
// add getter and setter for myString
// or delegate needed methods to myString object.
}
Of course, then you must be using this class, not the String class in your lists.
Regarding Tim's answer you can do something like this:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone{
public static void main (String[] args) throws java.lang.Exception
{
MyString my = new MyString();
String testString = "bb";
my.setMyString(testString);
System.out.println(my.equals(testString));
}
}
class MyString {
private String myString;
#Override
public boolean equals(Object o){
return o.equals(myString);
}
public String getMyString(){
return myString;
}
public void setMyString(String newString){
myString = newString;
}
}
The output is true.

Categories

Resources