Trouble calling a non-static method from an abstract class - java

I'm trying to call getSetting() from SettingsItem.java in SingleChoiceViewHolder.java. Is there a way to call getSetting() while keeping SettingsItem a non-static abstract class? Here's what I tried to add to SingleChoiceViewHolder.java, however Android Studio says that 'SettingsItem' is abstract; cannot be instantiated.:
SettingsItem instance = new SettingsItem();
instance.getSetting();
IntSetting setting = (IntSetting) getSetting();
mTextSettingDescription.setText(setting.getValue());
I also tried I tried converting SettingsItem to an interface and implementing it alongside SingleChoiceViewHolder extends SettingViewHolder but the original problem still remained.
The files are attached below.
SingleChoiceViewHolder.java:
public final class SingleChoiceViewHolder extends SettingViewHolder
{
private SingleChoiceSetting mItem;
private TextView mTextSettingName;
private TextView mTextSettingDescription;
public SingleChoiceViewHolder(View itemView, SettingsAdapter adapter)
{
super(itemView, adapter);
}
#Override
protected void findViews(View root)
{
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
}
#Override
public void bind(SettingsItem item)
{
mItem = (SingleChoiceSetting) item;
mTextSettingName.setText(item.getNameId());
if (item.getDescriptionId() == R.string.dynamic_descriptionId)
{
SettingsItem instance = new SettingsItem();
instance.getSetting();
IntSetting setting = (IntSetting) getSetting();
mTextSettingDescription.setText(setting.getValue());
}
if (item.getDescriptionId() > 0 && item.getDescriptionId() != R.string.dynamic_descriptionId)
{
mTextSettingDescription.setText(item.getDescriptionId());
}
}
#Override
public void onClick(View clicked)
{
getAdapter().onSingleChoiceClick(mItem);
}
SettingsItem.java:
public abstract class SettingsItem
{
public static final int TYPE_HEADER = 0;
public static final int TYPE_CHECKBOX = 1;
public static final int TYPE_SINGLE_CHOICE = 2;
public static final int TYPE_SLIDER = 3;
public static final int TYPE_SUBMENU = 4;
public static final int TYPE_INPUT_BINDING = 5;
public static final int TYPE_RADIO_BUTTON = 6;
private String mKey;
private String mSection;
private int mFile;
private Setting mSetting;
private int mNameId;
private int mDescriptionId;
public SettingsItem(String key, String section, int file, Setting setting, int nameId, int descriptionId)
{
mKey = key;
mSection = section;
mFile = file;
mSetting = setting;
mNameId = nameId;
mDescriptionId = descriptionId;
}
public String getKey()
{
return mKey;
}
public String getSection()
{
return mSection;
}
public int getFile()
{
return mFile;
}
public Setting getSetting()
{
return mSetting;
}
public void setSetting(Setting setting)
{
mSetting = setting;
}
public int getNameId()
{
return mNameId;
}
public int getDescriptionId()
{
return mDescriptionId;
}
public abstract int getType();
}

Since getSetting() is not a static method, you need to invoke it on an instance of some concrete class that extends the abstract class SettingsItem.
Think about it. If you have two instances of such a class, and the mSetting variable is different for the two instances, which one should be returned from a static-like call to getSetting()?

By definition abstract class means it is not instantiated but you can inherit from it. If you want to create many different objects with the same values but different names you can just extend SettingsItem.
Also, if you want more abstraction for future use you can create an interface with the same methods as the abstract methods in case you need to make customize methods for a different settings item.
Example:
interface SettingsInterface {
void doSomething();
}
class abstract SettingsItem implements SettingsInterface {
public void doSomething() {
System.out.println("Hello");
}
}
class RegularSettings extends SettingsItem {}
class CustomSettings implements SettingsInterface {
public void doSomething() {
System.out.println("Goodbye");
}
}
class TestClass {
public static void testAbstract(SettingsItem extendedAbstract) {
extendedAbstract.doSomething();
}
public static void testInterface(SettingsInterface interface) {
interface.doSomething();
}
public static void main(String[] args) {
SettingsItem abstractExtended = new RegularSettings();
// also could be CustomSettings instead of SettingsInterface
SettingsInterface customClass = new CustomSettings();
testInterface(abstractExtended);
testInterface(customClass);
testAbstract(abstractExtended);
// will throw errors since it doesn't extend SettingsItem
testAbstract(customClass);
}
}

Related

How can I provide this sort of String builder class?

I like to have a Drive class where all files and folders for a project are managed.
My first attempt was pretty easy like a lot of functions (most of them with arguments).
Now I try to make it more fancy because it became more and more annoying to have a lot of functions, in which the desired one can be found. To not have an XY-problem here, I start with my dream.
I like to construct the Drive class in a way, so that it is super easy to find a certain file or folder.
If you look in the main function, I can find every needed file by writing a point and look which subclasses/methods are proposed to continue, till I find it and add .str to it. At every point, only the subclasses/methods will be proposed which makes sense at this point.
It almost works! It is more complicated to write and maintain as the first approach, but If I use it very often, it could be worth it.
I can:
go into subfolders
go into subfolders with name inside the argument
But there is an error if I define a fixed-name-subfolder of a fluid-name-folder like in the code below.
Now my questions:
how can I change the code so the main Function doesn't show this error?
would you recommend a completely different approach to the "make it easy to find strings inside a huge list of strings via making collections inside collections... of strings"-problem?
package utilities;
public class Drive_draft {
private static final String fs = System.getProperty("file.separator");
public static final String str = System.getProperty("user.home").concat(fs);
public static class IeCreation {
public static final String str = Drive_draft.str.concat(".meetings").concat(fs);
public static class Abstract {
public static final String str = IeCreation.str.concat("Abstracts").concat(fs);
}
public static class Meeting {
public static final String str = IeCreation.str.concat("Ueberordnungen").concat(fs);
}
}
public static class MetsSIPs {
public static final String str = Drive_draft.str.concat("workspace").concat(fs).concat("metsSIPs").concat(fs);
public static class preSIPs {
public static final String str = MetsSIPs.str.concat("preSIPs").concat(fs);
}
public static class RosettaInstance {
private static class MaterialflowId {
public static String str;
private static class ProducerId {
public static String str;
private static class Abstract {
public static String str;
public static class Mets {
public static final String str = Abstract.str.concat("content").concat(fs).concat("ie1.xml");
}
}
private static class Meeting {
public static String str;
}
public static Abstract Abstract (String value) {
Abstract ret = new Abstract();
ProducerId.Abstract.str = str.concat(value).concat(fs);
return ret;
}
public static Meeting Meeting (String value) {
Meeting ret = new Meeting();
ProducerId.Meeting.str = str.concat(value).concat(fs);
return ret;
}
}
public static ProducerId ProducerId (String value) {
ProducerId ret = new ProducerId();
MaterialflowId.ProducerId.str = str.concat(value).concat(fs);
return ret;
}
}
public static MaterialflowId MaterialflowId (String value) {
MaterialflowId ret = new MaterialflowId();
MaterialflowId.str = str.concat(value).concat(fs);
return ret;
}
}
public static class Dev extends RosettaInstance {
public static final String str = MetsSIPs.str.concat("dev").concat(fs);
}
public static class Test extends RosettaInstance {
public static final String str = MetsSIPs.str.concat("test").concat(fs);
}
public static class Prod extends RosettaInstance{
public static final String str = MetsSIPs.str.concat("prod").concat(fs);
}
}
#SuppressWarnings("static-access")
public static void main(String[] args) {
System.out.println(Drive_draft.MetsSIPs.Dev.str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("1").str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("2").str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("1").ProducerId("t").str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("1").ProducerId("t").Abstract("est").str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("1").ProducerId("t").Meeting("oast").str);
System.out.println(Drive_draft.MetsSIPs.Dev.MaterialflowId("1").ProducerId("t").Abstract("est").Mets.str); //Error: Mets cannot be resolved or is not a field
}
}
You can encode your "directory" structure with interfaces, with each interface declaring what the user can do next. Then the implementation can use a StringBuilder to just append the appropriate snippets and keep returning this.
// PathBuilderInterfaces.java
public class PathBuilderInterfaces {
public interface Buildable {
String build();
}
public interface Drive extends Buildable {
IeCreation ieCreation();
MetsSIPs metsSIPs();
}
public interface IeCreation extends Buildable {
String ieCreationAbstract();
String meeting();
}
public interface MetsSIPs extends Buildable {
RosettaInstance dev();
RosettaInstance test();
RosettaInstance prod();
}
public interface RosettaInstance extends Buildable {
MaterialFlowId materialFlowId(String value);
}
public interface MaterialFlowId extends Buildable {
ProducerId producerId(String value);
}
public interface ProducerId extends Buildable {
Abstract producerIdAbstract(String value);
String meeting(String value);
}
public interface Abstract extends Buildable {
String mets();
}
}
// PathBuilder.java
import static com.example.somepackage.PathBuilderInterfaces.*;
public class PathBuilder implements Drive, IeCreation, MetsSIPs, RosettaInstance, MaterialFlowId, ProducerId, Abstract{
private StringBuilder builder = new StringBuilder(str);
private static final String fs = System.getProperty("file.separator");
public static final String str = System.getProperty("user.home").concat(fs);
public static Drive drive() {
return new PathBuilder();
}
#Override
public String build() {
return builder.toString();
}
#Override
public IeCreation ieCreation() {
builder.append(".meetings").append(fs);
return this;
}
#Override
public MetsSIPs metsSIPs() {
builder.append("workspace").append(fs).append("metsSIPs").append(fs);
return this;
}
#Override
public RosettaInstance dev() {
builder.append("dev").append(fs);
return this;
}
#Override
public RosettaInstance test() {
builder.append("test").append(fs);
return this;
}
#Override
public RosettaInstance prod() {
builder.append("prod").append(fs);
return this;
}
#Override
public MaterialFlowId materialFlowId(String value) {
builder.append(value).append(fs);
return this;
}
#Override
public ProducerId producerId(String value) {
builder.append(value).append(fs);
return this;
}
#Override
public Abstract producerIdAbstract(String value) {
builder.append(value).append(fs);
return this;
}
#Override
public String meeting(String value) {
builder.append(value).append(fs);
return build();
}
#Override
public String mets() {
builder.append("content").append(fs).append("ie1.xml");
return build();
}
#Override
public String ieCreationAbstract() {
builder.append("Abstracts").append(fs);
return build();
}
#Override
public String meeting() {
builder.append("Ueberordnungen").append(fs);
return build();
}
}
Usage:
// in a main method somewhere
System.out.println(
PathBuilder.drive()
.metsSIPs()
.dev()
.materialFlowId("1")
.producerId("t")
.producerIdAbstract("est")
.mets());

Strategy pattern with inner enum

I'm trying to get rid of big switch statement from my code and I thought that Strategy pattern based on my existing enum would be nice. The concept is like:
public class MyStrategy {
public MyStrategy() {
Option.Option1.setMethodToExecute(this::action1);
Option.Option2.setMethodToExecute(this::action2);
}
public void executeChoosenMethod(int i) {
Option.values()[i].execute();
// instead of
// switch(convertItoOption()) {
// case Option1:...
// case Option2:...
// }
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1, Option2;
private InvokeAction methodToExecute;
public void setMethodToExecute(InvokeAction methodToExecute) {
this.methodToExecute = methodToExecute;
}
public void execute() {
methodToExecute.execute();
}
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}
so I can use it like:
public class StrategyTest {
public static void main(String[] args) {
MyStrategy strategy = new MyStrategy();
//user choose 0 or 1
strategy.executeChoosenMethod(0);
strategy.executeChoosenMethod(1);
}
}
but I don't like this part with Option.Option1.setMethodToExecute(this::action1); since my enum has more and more options and I would like to have all of this inside enum. What would be perfect is something like this:
public class MyStrategy {
public void executeChoosenMethod(int i) {
Option.values()[i].execute();
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1(MyStrategy.this::action1),
Option2(MyStrategy.this::action2);
private InvokeAction methodToExecute;
private Option(InvokeAction method) {
methodToExecute = method;
}
public void execute() {
methodToExecute.execute();
}
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}
but this is impossible since enum is static and I don't have access to enclosing instance by MyStrategy.this. I need enum, because I have set of options and it is convenient to use methods like values() or valueOf(), but what I would like to have is single line invoke instead of growing switch.
Do you have any ideas how to achieve sometghing like this or is there any workaround to make this enum constructor call possible Option1(MyStrategy.this::action1) ?
With enums you could implement it like this:
public class MyStrategy {
public void executeChoosenMethod(int i) {
Option.values()[i].execute(this);
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private enum Option {
Option1(MyStrategy::action1),
Option2(MyStrategy::action2);
private InvokeAction methodToExecute;
private Option(InvokeAction method) {
methodToExecute = method;
}
public void execute(MyStrategy s) {
methodToExecute.execute(s);
}
}
#FunctionalInterface
private interface InvokeAction {
void execute(MyStrategy s);
}
}
This uses the fact the with lambdas you can make method references to arbitrary instance methods and call them on a specific instance by passing in the instance as first parameter.
you're right. This isn't possible with enum. But why not just use a good old class:
public class MyStrategy {
public MyStrategy() {
buildUp();
}
public void executeChoosenMethod(int i) {
actions.get(i).execute();
}
private void action1() {
System.out.println("action1");
}
private void action2() {
System.out.println("action2");
}
private List<InvokeAction> actions = new ArrayList<>();
private void buildUp() {
actions.add(this::action1);
actions.add(this::action2);
}
#FunctionalInterface
private interface InvokeAction {
void execute();
}
}

Create Enum with list of the same object

I would like to create an enum containing one attribut, a list of objects extending the same interface or the same abstract class.
The objective is to have a loop on each list of my enum to call methods dynamically.
public interface Regles {
void verifier();
}
public class Regle01 implements Regles {
#Override
public void verifier() {
}
}
public class Regle02 implements Regles {
#Override
public void verifier() {
}
}
public enum ListRegles {
ENUM1(Arrays.asList(new Regle01(), new Regle02())),
ENUM2(Arrays.asList(new Regle01()))
private List<Regles> regles = new ArrayList<Regles>();
ListRegles(List<Regles> r) {
regles = r;
}
}
how can i do this please ?
enum:
public enum ListRegles {
ENUM1(new Regle01(),new Regle02()),
ENUM2(new Regle01());
private List<Regles> regles ;
ListRegles(Regles... regles) {
this.regles = new ArrayList<>(Arrays.asList(regles));
}
public void verify() {
for (Regles regle : regles) {
regle.verifier();
}
}
}
Will call verifier for Regle01 and Regle02
ListRegles.ENUM1.verify();

Passing a value between classes

I need to pass a string from class to another class in Java (Bukkit), I have already read some similar questions, but I can't solve the problem.
I have a Main class
public class Main extends JavaPlugin {
#Override
public void onEnable() {
new PlayerListener(this);
this.saveDefaultConfig();
String bannedBlocksString = this.getConfig().getString("bannedBlocks");
}
#Override
public void onDisable() {
}
}
And another class "PlayerListener"
public class PlayerListener implements Listener {
public PlayerListener(Main plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
// public static final String bannedBlocksString = "DIAMOND_BLOCK; EMERALD_BLOCK";
public static final String[] bannedBlocks = bannedBlocksString.split("; ");
public static boolean isBannedBlock(String[] bannedBlocks, String blockPlaced) {
boolean returnValue = false;
for (String bannedBlock : bannedBlocks) {
if(blockPlaced.equalsIgnoreCase(bannedBlock)){
returnValue = true;
}
}
return returnValue;
}
#EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
String blockPlaced = event.getBlockPlaced().getType().toString();
if(!event.getPlayer().hasPermission("antibuild.block.noplace") && isBannedBlock(bannedBlocks, blockPlaced)) {
event.setCancelled(true);
event.getPlayer().sendMessage(ChatColor.RED + "You can not place this block.");
}
}
}
How can I get the value of bannedBlocksString in Main from the class "PlayerListener"?
Try this, I hope it works:
From Main:
PlayerListener pl = new PlayerListener(this);
this.saveDefaultConfig();
String [] bannedBlocksString = pl.getBannedBlocks();
From PlayerListener you have to declare get method:
public String [] getBannedBlocks(){
return this.bannedBlocks;
}
If you uncomment the bannedBlocksString in the PlayerListener then you can always access it in the Main class using PlayerListener.bannedBlocksString as the variable is static.
If you want to do it the other way arround and assign the value you need to remove the final from the variable and use the code beneath.
PlayerListener.bannedBlocks = bannedBlocksString.split("; ");

Java Failure on JUnit Case Calling a Method from a Subclass

I have the constructor Alieni from the subclass Alieni of the class Settore that sets the name ALIENI from the enum Nome to a certain Settore (composed by the integers coordinataX and coordinataY).
The test I'm trying to make is to verify that after running the method Alieni to a Settore(3,10) when I run the method getSettoreNome on the same Settore it should return the name ALIENI but it returns null.
import static org.junit.Assert.*;
public class Settore {
private Nome settoreNome;
private final int coordinataX;
private final int coordinataY;
public Settore (int coordinataX, int coordinataY){
this.coordinataX=coordinataX;
this.coordinataY=coordinataY;
}
public Nome getSettoreNome() {
return settoreNome;
}
public void setSettoreNome(Nome settoreNome) {
this.settoreNome = settoreNome;
}
}
public enum Nome {
SICURO, PERICOLOSO, SCIALUPPA, ALIENI, UMANI
}
public class Alieni extends Settore {
public Alieni(int coordinataX, int coordinataY) {
super(coordinataX, coordinataY);
setSettoreNome(Nome.ALIENI);
}
}
public class AlieniTest {
#Test
public void testAlieni() {
Settore settore = new Settore(3,10);
new Alieni(3,10);
assertEquals(Nome.ALIENI, settore.getSettoreNome());
}
}
You aren't assigning the new instance of Alieni anywhere. Presumably you'd meant to assign it to settore:
public class AlieniTest {
#Test
public void testAlieni() {
Settore settore = new Alieni(3,10);
assertEquals(Nome.ALIENI, settore.getSettoreNome());
}
}

Categories