I have a base class FiniteStateMachine which has a list of State. The states can only be instantiated through the FSM, so I can make sure the list is updated.
public class FiniteStateMachine {
private List<State> states = new ArrayList<State>();
public State addState(String name) {
State s = new State(name);
states.add(s);
return s;
}
protected void addState(State s) {
states.add(State s);
}
public static class State {
private String name;
protected State(String name) { this.name = name; }
}
}
Now, I want to extend both the FiniteStateMachine and State classes into MyFSM and MyState classes. I still want to make sure the new MyState states can only be created through the FSM, to ensure they are part of the list.
This is what I have done so far:
public MyState extends FinitStateMachine.State {
private int n;
protected MyState(int n, String name) {
super(name);
this.n = n;
}
}
public MyFSM extends FiniteStateMachine {
#Override
public State addState(String name) {
throw new UnsupportedOperationException();
}
public MyState addState(int n, String name) {
MyState s = new MyState(n, name);
super.addState(s);
return s;
}
}
I am not sure I am doing it right.
First, the original State class is an inner class of FiniteStateMachine, and here I am extending it outside my new class MyFSM.
Second, I had to add a new method to the original FiniteStatMachine
protected void addState(State s) {
states.add(State s);
}
otherwise I don't know how could I have attached a state of my new MyState class to the FiniteStateMachine list.
Third, instead of overriding the addState(name) method I kind of crippled it and throw an exception and instead put a whole new method to return the new class.
If there is a coding pattern for these situations I am not aware of it. But I'd like to know, so I don't go reinventing the wheel.
If you make the list variable protected, you may access it from child classes too, without the add method. It depends on what you want to do later, and how visible you want the list to be. If you want to be able to add states from outside of the inheritance hierarchy, or if you don't want the list to be visible within the whole package,you may need the addState method though.
Related
Can we call a protected ArrayList from one class to another class, where it can be used for "all methods" in the 'another' class.
for example:
public class ArrayListClass {
protected Arraylist<SomeClass> someClass = new Arraylist<>();
}
Then I want to use the ArrayList in all of the methods in another class
public class another {
private void method1() {
//use the same arraylist here
}
private void method2() {
//use the same arraylist here
}
public void method3() {
// use the same arraylist here
}
There are multiple approaches you can take. In general, you're trying to pass data/variable from one Class to another.
But since you're using protected access modifier, your options will be limited.
If the 'AnotherClass' is in the same package, you could use inheritance (as has been mentioned in the comments) or you could instantiate a new instance as advised in this answer.
If 'AnotherClass' is in a different package, the only option you have is to use inheritance.
If this doesn't work, consider changing the access modifier.
More info on Protected access modifier:
https://www.geeksforgeeks.org/protected-keyword-in-java-with-examples/
Sure, just add access methods to ArrayListClass:
public class ArrayListClass {
protected Arraylist<String> string = new Arraylist();
public getTheList () { return string; }
// more access methods
}
In your class Another, create in instance of your ArrayListClass:
public class another {
private ArrayListClass alc;
public another () { // default constructor
alc = new ArrayListClass ();
}
private void method1() {
alc.getTheList.add ("Foo");
}
But, if you do that, you should think about why string is protected in the first place.
So I've got an Object class Item and an Object class Trap. These two share variables called name and icon. I want to be able to put both of these classes into one array called special and be able to access the components of Item and Trap by using special. Here's my code that I need to work.
if (special[x][y] == null)
return 0;
System.out.print(special[x][y].icon); /* here's where the issue is */
return 1;
What should special be an array of? Should I use an interface? And if so, how? I've been reading everywhere but I don't know how to describe my problem.
Give this a try:
class Base
{
String name;
Icon icon;
}
class Item extends Base { }
class Trap extends Base { }
List<Base> special = new ArrayList<>();
alternatively, you can make Base an interface, and use the implements keyword instead of extends for Item and Trap.
One way that may work is to use a superclass (class, abstract class, interface all work). This is a bad name for the superclass, but I'm sure that you will get the idea:
public class Thing {
String icon; // Every class that extends Thing has an icon
String name; // Every class that extends Thing has a name
public Thing(String newIcon, String newName) {
icon = newIcon;
name = newName;
}
public String getIcon() {
return this.icon;
}
public String getName() {
return this.name;
}
}
public class Trap extends Thing {
public Trap() {
super("newIcon", "newName"); // Sets this Traps's name and icon values
}
}
public class Item extends Thing {
public Item() {
super("newIcon", "newName"); // Sets this Item's name and icon values
}
}
You can add whatever methods/variables that you want to Trap and Item, and, as long as they are legal in and of themselves, they will work.
Make an interface for Item and Trap which contains the methods they should share.
public interface GameObject {
String getName();
Image getIcon();
}
You can then create the Item and Trap classes by implementing this interface. For example
public class Trap implements GameObject {
private String name;
private Image icon;
public GameObject(String name, Image icon) {
this.name = name;
this.icon = icon;
} ...
By declaring this class implements GameObject it means we have to create the getName and getIcon methods. You do this by using an #Override annotation.
public class Trap implements GameObject {
private String name;
private Image icon;
public GameObject(String name, Image icon) {
this.name = name;
this.icon = icon;
}
#Override
public String getName() {
return name;
}
#Override
public Image getIcon() {
return icon;
}
}
Now that it implements GameObject we can add it to a list that holds GameObject types
List<GameObject> special = new ArrayList<>();
myList.add(new Trap(myTrapName, myTrapImage));
myList.add(new Item(myItemName, myItemImage));
We can then call the methods without worrying if that particular GameObject is an Item or a Trap
for (GameObject obj : special) {
System.out.println(obj.getName());
}
You should use an Interface
public interface SpecialInterface{
//you actually do not need any code, usually interfaces are called something+able
String getIcon();//this method will be filled in all the objects implementing this interface
}
So now you implement the interface in both your classes, for example:
public class Trap implements SpecialInterface{
//...
}
Now that you want to iterate your items and traps, you can do something like:
System.out.println(special[x][y].getIcon());
or..
if(special[x][y] instanceof Trap){
Trap oneTrap = (Trap) special[x][y]; //here you transform your SpecialInterface object in a Trap object
System.out.println(special[x][y].icon);
}else{
Item oneItem = (Item) special[x][y];
System.out.println(special[x][y].icon);
}
Note: Your Trap and Item objects should be declared like:
SpecialInterface trap = new Trap();
or
SpecialInterface item = new Item();
Otherwise you can't insert this objects in your matrix.
What should special be an array of? Should I use an interface? And if so, how?
If you want an array that can accommodate elements of two different types, then its element type must be a supertype of both. That could be an interface that both types implement, or a superclass of both.
I'd encourage you to access the members via accessor methods (e.g. getIcon()). If you insist on accessing them directly, as in your example, then the interface option is not possible, and the members you want to access must belong to the superclass (or one of its superclasses).
For example,
public interface GameObject {
String getName();
Icon getIcon();
}
public class Trap implements GameObject {
private final String name;
private final Icon icon;
public Trap(String name, Icon icon) {
this.name = name;
this.icon = icon;
}
#Override
public String getName() {
return name;
}
#Override
public Icon getIcon() {
return icon;
}
}
(... and similar for Item ...)
GameObject[][] special = /* ... */;
// ...
if (special[x][y] == null) {
return 0;
}
System.out.print(special[x][y].getName());
return 1;
public class Entity {
String name;
Icon icon;
}
public class Item extends Entity {
...
...
}
public class Trap extends Entity {
...
...
}
Entity[][] special = new Entity[5][10];
and now you can insert either of the two classes in special 2D array and you can use the exact same code that you've supplied in your question.
if (special[x][y] == null)
return 0;
System.out.print(special[x][y].icon); /* here's where the issue is */
return 1;
there I'm pretty new to Java and have german class and method titles. This Code is meant to give a string output for every class extending "Musiker". I have already looked on SO but my problem is that changing it to static gives an error on the class itself. The main reason why I open a new Question is, that every other class is working as planned. And please don't wonder why the Strings look weird, the Book I copied this from is meant to be humoristic.
public class Proberaum {
public static void main(String[] args) {
try {
Musiker saenger = new Saenger();
Musiker gitarrist = new Gitarrist();
Musiker bassist = new Bassist();
Musiker trompeter = new Trompeter();
Musiker backgroundSaengerin = new BackgroundSaengerin();
machtMusik(saenger, gitarrist, bassist, trompeter, backgroundSaengerin);
} catch(Exception e) {
new Exception().printStackTrace();
}
}
public static void machtMusik(Musiker... gruppe) {
for(Musiker musiker : gruppe) {
musiker.musizieren();
}
}
public class Musiker {
private String name;
private int alter;
private Band band;
public void musizieren() {
System.out.println("OO Mmmmmmmmh, OO Mmmmmmmmh");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAlter() {
return alter;
}
public void setAlter(int alter) {
this.alter = alter;
}
public Band getBand() {
return band;
}
public void setBand(Band band) {
this.band = band;
}
}
public class Band {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Saenger extends Musiker {
#Override
public void musizieren() {
this.singen();
}
public void singen() {
System.out.println("Oh, bäbi, juuuu a mei sannnnscheiiiiin");
}
}
public class BackgroundSaengerin extends Saenger {
}
public class Bassist extends Musiker {
}
public class Gitarrist extends Musiker {
public void musizieren() {
System.out.println("Tschiiiiiingzäääängggggg");
}
}
public class Trompeter extends Musiker {
}
}
Your Saenger class is actually a non-static member of the Proberaum class. Because it's non-static, you actually need to create an instance of Proberaum before you can use any of these classes:
Proberaum proberaumObject = new Proberaum();
Musiker saenger = new proberaumObject.Saenger();
In your case, classes inside classes is probably not what you want to do. If you extract each of your classes into its own file, you should find your problem going away. (If that's not possible for whatever reason, declaring your subclasses as static should work too.)
Like Joe C also mentioned in his answer: the core of the problem is that your classes Saenger, Musiker, etc etc. are all nested classes (nested inside Proberaum), but they are defined as non-static.
In Java, non-static nested classes are called "inner classes". Inner classes have implicit access to their enclosing class members (even private ones), but of course the flipside of this is that there first needs to be an object of that enclosing class for the inner class to reference. That is why the compiler is complaining in your example: you're trying to create an object of class Saenger, which is an inner class of Proberaum, so to create that object it needs to have a reference to an object of type Proberaum. Since you're doing the object creation in the (static) main method, no such object exists.
So, to fix, you have to change your inner classes. Easiest is to declare them all static. Note that you can do this is in addition to be making them public:
public static class Seanger extends Musiker { ...
As also remarked elsewhere however, you really should not put every class in the same file. Learn to work with one class per file, it's the Java Way™.
Instead of declaring the nested classes as static, one can alternatively create objects of nested classes like mentioned below.
Proberaum proberaumObject = new Proberaum();
Musiker saenger = proberaumObject.new Saenger();
I want to achieve method chaining in Java.
How can I achieve it?
Also let me know when to use it.
public class Dialog {
public Dialog() {
}
public void setTitle(String title) {
//Logic to set title in dialog
}
public void setMessage(String message) {
//Logic to set message
}
public void setPositiveButton() {
//Logic to send button
}
}
I want to create method chaining that I can use as follows:
new Dialog().setTitle("Title1").setMessage("sample message").setPositiveButton();
or like
new Dialog().setTitle("Title1").setMessage("sample message");
or like
new Dialog().setTitle("Title1").setPositiveButton();
Have your methods return this like:
public Dialog setMessage(String message)
{
//logic to set message
return this;
}
This way, after each call to one of the methods, you'll get the same object returned so that you can call another method on.
This technique is useful when you want to call a series of methods on an object: it reduces the amount of code required to achieve that and allows you to have a single returned value after the chain of methods.
An example of reducing the amount of code required to show a dialog would be:
// Your Dialog has a method show()
// You could show a dialog like this:
new Dialog().setMessage("some message").setTitle("some title")).show();
An example of using the single returned value would be:
// In another class, you have a method showDialog(Dialog)
// Thus you can do:
showDialog(new Dialog().setMessage("some message").setTitle("some title"));
An example of using the Builder pattern that Dennis mentioned in the comment on your question:
new DialogBuilder().setMessage("some message").setTitle("some title").build().show();
The builder pattern allows you to set all parameters for a new instance of a class before the object is being built (consider classes that have final fields or objects for which setting a value after it's been built is more costly than setting it when it's constructed).
In the example above: setMessage(String), setTitle(String) belong to the DialogBuilder class and return the same instance of DialogBuilder that they're called upon; the build() method belongs to the DialogBuilder class, but returns a Dialog object the show() method belongs to the Dialog class.
Extra
This might not be related to your question, but it might help you and others that come across this question.
This works well for most use cases: all use cases that don't involve inheritance and some particular cases involving inheritance when the derived class doesn't add new methods that you want to chain together and you're not interested in using (without casting) the result of the chain of methods as an object of the derived.
If you want to have method chaining for objects of derived classes that don't have a method in their base class or you want the chain of methods to return the object as a reference of the derived class, you can have a look at the answers for this question.
Just add a static builder method, and create another set of the setter methods.
For example
class Model {
private Object FieldA;
private Object FieldB;
public static Model create() {
return new Model();
}
public Model withFieldA(Object value) {
setFieldA(value);
return this;
}
public Model withFieldB(Object value) {
setFieldB(value);
return this;
}
}
...
And use it like
Model m = Model.create().withFieldA("AAAA").withFieldB(1234);
example of reducing the amount of code required to show a dialog would be:
package com.rsa.arraytesting;
public class ExampleJavaArray {
String age;
String name;
public ExampleJavaArray getAge() {
this.age = "25";
return this;
}
public ExampleJavaArray setName(String name) {
this.name = name;
return this;
}
public void displayValue() {
System.out.println("Name:" + name + "\n\n" + "Age:" + age);
}
}
another class
package com.rsa.arraytesting;
public class MethodChaining {
public static void main(String[] args) {
ExampleJavaArray mExampleJavaArray = new ExampleJavaArray();
mExampleJavaArray.setName("chandru").getAge().displayValue();
}
}
In case if you are using lombok, you can use parameter in your lombok.config:
lombok.accessors.chain = true
Or for particular data classes you can declare #Accessors(chain = true) annotation:
import lombok.experimental.Accessors;
#Accessors(chain = true)
#Data
public class DataType {
private int value;
// will generate setter:
public DataType setValue(int value) {
this.value = value;
return this;
}
}
Let's say we have a class with the following method:
public class Entry {
private String name;
public static Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
This class may be subclassed (e.g. SubEntry), and the logic behind "getOrCreate" does not change. But the subclasses should not return a new object of the type Entry, but of the type of the respective subclass (e.g. return SubEntry(name))
How can I realize this without reimplementing the method getOrCreate for every subclass of Entry? Is there a term for this kind of technique?
Subclassing Entry does not affect the getOrCreate method because static methods are not part of a class instance; they do not logically belong in any class.
If you instead move getOrCreate into a non-static Factory class, you can use some Generics magic to determine the returned type:
public class Entry {
private String name;
}
abstract class AbstractEntryFactory<T extends Entry>
public abstract T getOrCreate(String name);
}
public class EntryFactory extends AbstractEntryFactory<Entry>
#Override
public Entry getOrCreate(String name) {
// ...
return new Entry(name);
}
}
public class SubEntryFactory extends AbstractEntryFactory<SubEntry>
#Override
public SubEntry getOrCreate(String name) {
// ...
return new SubEntry(name);
}
}
Actually calling the getOrCreate would look different from what it would look like with your code. Instead of this:
Entry myEntry = Entry.getOrCreate("my name");
It would instead look like this:
Entry myEntry = new EntryFactory().getOrCreate("my name");
Or this:
SubEntry myEntry = new SubEntryFactory().getOrCreate("my name");
Assuming you wanted to be able to call Entry.getOrCreate() to create a type of SubEntry, you'll have to pass along some extra information. The reason is that the getOrCreate() method is not inherited by SubEntry, since it is a static method. So if you want to call it the way I mentioned, you'll have to pass along the class name that you want to create. In the code below there are no checks to validate that Class clazz is an Entry or a subtype, but this gives you a start.
import java.lang.reflect.Constructor;
public class TestClass {
public static void main(String[] args) {
Entry entry = (Entry)Entry.getOrCreate("entry", Entry.class);
SubEntry subEntry = (SubEntry)SubEntry.getOrCreate("subEntry", SubEntry.class);
System.out.println("entry class: " + entry.getClass().getName());
System.out.println("subEntry class: " + subEntry.getClass().getName());
}
}
class Entry {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static Object getOrCreate(String name, Class clazz) {
// If a constructor is created that takes a String, such as "public Entry(String name)",
// then each sub class will need to implement that method. Instead I used a getter and
// setter for the name attribute.
try {
Entry entry = (Entry)clazz.newInstance();
entry.setName(name);
return entry;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
class SubEntry extends Entry {
}
The end result is this output:
entry class: Entry
subEntry class: SubEntry
There are two questions you are asking:
How do I do this?
What is this technique called?
The second one is much more important than the first.
It seems to me like what you are trying to achieve is similar to the concept of cloning (link) or virtual constructor. But you would like this to be a static method, which raises the question as to why? Since a static method is tied to a certain class, not an instance, you should call it through that class in which case you may just as well explicitly be calling new. But having searched for "retrive class in static context" I would say it is not possible to do exactly what you wrote in the question.
If you convert the static method to a normal method, this can be done by using reflection:
class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
public Entry() {
this.name = null;
}
public Entry getOrCreate(String name) {
try {
return getClass().getConstructor(String.class).newInstance(name);
} catch (Exception e) {
return new Entry(name);
}
}
}
class BetterEntry extends Entry {
public BetterEntry(String name) {
super(name);
}
public BetterEntry() {
super();
}
}
You would then be calling the function from an instance, like so:
Entry a = new Entry().getOrCreate("First");
Entry b = new BetterEntry().getOrCreate("Second");
Entry c = b.getOrCreate("Third");
The dynamic types of a, b, c are Entry, BetterEntry and BetterEntry. You could leave out the default constructors, but I added them to make calling getOrCreate feel more like a static method.
If you really want the method to be static, the simplest way would be to just reimplement this function in every subclass.