I have an abstract class which has a method used by all classes that extend the class. That method is identical for each class so I don't want to have to write it over and over in those classes. The problem is that the method uses 2 variables that are declared in each class. I can't have the method in the abstract class without having those variables int eh abstract class. But if I do that, they take on the value specified in the abstract class, not the classes that extend it. How can I fix this?
Example code:
public abstract class Example {
public String property1 = ""
public String property2 = ""
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(property1);
propertyList.add(property2);
return property1;
}
}
public class ExampleExtension extends Example {
public String property1 = "this is the property";
public String property2 = "this is the second property";
}
You should limit the scope of the fields to private in the abstract class and declare a constructor for populating the values:
public abstract class Example {
private final String property1;
private final String property2;
protected Example(String property1, String property2) {
this.property1 = property1;
this.property2 = property2;
}
//...
}
Subclasses would then initialize the field values in their constructors by calling the super constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
super("value1", "value2");
// initialize private fields of ExampleExtension, if any
}
// ...
}
You don't have to override the variables. You can set the initial values of your properties in the constructor:
public class ExampleExtension extends Example {
public ExampleExtension() {
property1 = "this is the property";
property2 = "this is the second property";
}
}
A better way is to use a constructor with parameters though, as Mick Mnemonic suggest in the other answer.
IMO Mick's solution is the most pragmatic, although note that you also have the option to make the properties abstract, and then use subclass polymorphicism to require that subclasses override the property implementation:
public abstract class Example {
public abstract String getProperty1();
public abstract String getProperty2();
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return propertyList;
}
}
public class ExampleExtension extends Example {
public String getProperty1() { return "this is the property"};
public String getProperty2() { return "this is the second property"};
}
Make what differs(e.g. property1,property2) abstract method in this case . Search for related reading on template pattern
public abstract class Example {
public ArrayList<String> getPropertyies() {
ArrayList<String> propertyList = new ArrayList<>();
propertyList.add(getProperty1());
propertyList.add(getProperty2());
return property1;
}
public abstract getProperty1();//overriden by other class that has diff value for property1
public abstract getProperty2();//overriden by other class that has diff value for property2
}
Related
i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?
Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {
public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();
I have a base class and a derived class, both designed to be immutable (ctor and getters omitted):
public class PageQuery<T> {
private final T queryFilter;
private PageCond pageCond; // pagination parameter
// E withPageCond(PageCond newPageCond) {
// return a brand new copy of `this` with `pageCond` replaced with `newPageCond`
// that can be reused across class hierarchy
// }
}
public class PageSortQuery<T> extends PageQuery<T>{
private final SortCond sortCond; // sorting parameter
}
How to add a method that returns defensive copy of this to the base class so that all classes in this hierarchy can benefit from it? Is there a way to accomplish it without clone()?
I don't know if you mean something like this, in this case if you call the withFilter method the origin would not become changed.
#AllArgsConstructor
public class Query <T> {
#Getter
private final String name;
#Getter
private final Predicate<T> filter;
public Query<T> withFilter(Predicate<T> filter){
return new DelegatingQuery<T>(this){
#Override
public Predicate<T> getFilter() {
return Query.this.filter;
}
};
}
static class DelegatingQuery<T> extends Query<T>{
#Delegate
private final Query<T> query;
public DelegatingQuery(Query<T> query) {
super(query.name,query.filter);
this.query = query;
}
}
}
I need help fixing my code with the basic concepts listed above. To save from clutter, I took a screen shot of the directions here: https://imgur.com/SdiotUi
However, when I run my code it isn't working. I know there are a lot of errors but I'm having trouble fixing them even though I've spent the past few hours googling the correct way to do this.
When I create the first constructors I am not sure if I am assigning the name and legs correctly, I am having trouble returning "true", I get an error calling the parent class taking one argument, and I don't think I am overriding the abstract class correctly.
My code:
public class Animal1 {
private String animalName;
public int numberOfLegs;
public Animal1(String name){
name = animalName;
name = "John";
}
public Animal1(String name, int legs){
name = animalName;
legs = numberOfLegs;
name = "Jack";
legs = 4;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public void isAMammal(){
return true;
}
public void isCarnivorous(){
return true;
}
public abstract class getHello{
}
}
public class Cat1 extends Animal1{
public Cat1(String name){
Animal1.name;
}
public abstract class getHello{
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(String name){
Animal1.name;
}
public abstract class getHello{
return "Woof";
}
}
public abstract class Animal1 { // If you want to have an abstract method, declare the class as abstract
private final String animalName;
private final int numberOfLegs; // better of using private and make it final since it's not going to change.
public Animal1(final String name, final int legs){ //better making the input parameters final since they are not supposed to be changed
//name = animalName;
//legs = numberOfLegs;//it assigned the field to an input parameter. that will take no effect on the object created.
animalName = name;
numberOfLegs = legs;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public boolean isAnimal(){ //boolean function needs a return type too!!
return true;
}
public boolean isCarnivorous(){
return true;
}
public abstract String getHello(); // an abstract method has same requirement as a normal method besides the abstract modifier. it will need a return type. And it ends with a semicolon
}
public class Cat1 extends Animal1{
public Cat1(final String name){
super(name, 4); //use super to call parent constructor
}
#Override
public String getHello(){
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(final String name){
super(name, 4);
}
#Override
public String getHello(){
return "Woof";
}
}
First, it looks like a few of your methods are declared as classes. I assume you wanted to make them abstract methods. They need to be changed to:
public abstract String getHello();
Note that abstract methods can only be declared in an abstract class. So, you need to redefine Animal1 as abstract.
public abstract class Animal1
Next, when you implement the abstract method, you define it as
public String getHello()
If you are using an IDE like Eclipse it will automatically offer to generate this method.
Finally, when using your constructor in your child classes like Cat1, you are trying to set "name" as if it was a static variable and bypassing the constructor you already had set for Animal1. The best way to correct this is to change the constructor in Cat1 and Dog1 to call the super constructor.
public Cat1(String name){
super(name);
}
I am creating an API that returns a list of Cars. The API user must be able to request that the list be filtered and sorted by a certain attribute (field) of the Cars class. How can I do that?
class Car {
public final String model;
public final String color;
public Car(String m, String c) {
model = m;
color = c;
}
}
class CarListRequest {
public final String sortBy;
public final String filterBy;
public final List<String> filterList;
public CarListRequest(String s, String f, List<String> list) {
sortBy = s;
filterBy = f;
filterList = list;
}
}
Is there a way to restrict, using Java language features, that sortBy and filterBy Strings cannot contain any other values than attributes (fields) of the Car class?
I know that I could use an enum to declare all attributes of Car however, that causes a duplication of Strings which I would like to avoid.
#hmc_jake 's reflection suggestion is quite valid. However, if you want to avoid reflection, you could do it using a class hierarchy:
class CarAttribute {
private String attrib;
public CarAttribute(String att){
attrib = att;
}
// add getters and/or setters for attrib ...
}
class CarModel extends CarAttribute {
}
class CarColor extends CarAttribute {
}
class Car {
public final CarModel model;
public final CarColor color;
public Car(CarModel m, CarColor c) {
model = m;
color = c;
}
}
class CarListRequest {
public final CarAttribute sortBy;
public final CarAttribute filterBy;
public final List<CarAttribute> filterList;
public CarListRequest(CarAttribute s, CarAttribute f, List<CarAttribute> list) {
sortBy = s;
filterBy = f;
filterList = list;
}
}
Using Reflection in Java, it is possible to inspect a class's fields.
When, for example, s is passed in, you can perform a check on the argument like so:
for (Field field : Car.class.getFields()) {
if (field.getName().equalsIgnoreCase(s)) {
Do something here to signal that s
was a valid Field of the Car class.
}
}
Doing this allows you to reflectively inspect the Car class in order to verify that the argument passed in is in-fact a field of that class.
Note, however, that if possible you should go with the enum or class hierarchy as reflection might be a little bit overkill for what you're trying to accomplish.
I have several interfaces all with the same constants - ID and ROOT. I also have a method into which I pass an object that will be an implementation of one of these interfaces.
How can I dynamically retrieve the value of the constant depending on the class passed in - i.e. I want to do something like the following:
public void indexRootNode(Node node, Class rootNodeClass)
{
indexService.index(node, rootNodeClass.getConstant('ID'),
rootNodeClass.getConstant('ROOT'));
}
In PHP this is easy, but is this possible in Java? I've seen this problem solved using accessors on the constant, but I want to retrieve the constant directly. Annotations won't help me here either.
Thanks
This can be achieved using reflection (also see corresponding javadoc).
public void indexRootNode(Node node, Class rootNodeClass)
{
Field idField = rootNodeClass.getField("ID");
Object idValue = idField.get(null);
Field rootField = rootNodeClass.getField("ROOT");
Object rootValue = rootField.get(null);
indexService.index(node, idValue, rootValue);
}
Maybe you may additionaly have to cast the values to the corresponding type.
Please read chapter 19 use interfaces only to define types from Joshua Bloch's Effective Java (in fact, please read the entire book)
Constants do not belong in an interface!!! Constants should be tied to implementing classes, not interfaces.
Either use non-constant methods:
// the implementing classes can define these values
// and internally use constants if they wish to
public interface BaseInterface{
String id(); // or getId()
String root(); // or getRoot()
}
public interface MyInterface1 extends BaseInterface{
void myMethodA();
}
public interface MyInterface2 extends BaseInterface{
void myMethodB();
}
or use an enum to tie things together:
public enum Helper{
ITEM1(MyInterface1.class, "foo", "bar"),
ITEM2(MyInterface2.class, "foo2", "baz"),
;
public static String getId(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getId();
}
public static String getRoot(final Class<? extends BaseInterface> clazz){
return fromInterfaceClass(clazz).getRoot();
}
private static Helper fromInterfaceClass(final Class<? extends BaseInterface> clazz){
Helper result = null;
for(final Helper candidate : values()){
if(candidate.clazz.isAssignableFrom(clazz)){
result = candidate;
}
}
return result;
}
private final Class<? extends BaseInterface> clazz;
private final String root;
private final String id;
private Helper(final Class<? extends BaseInterface> clazz,
final String root,
final String id){
this.clazz = clazz;
this.root = root;
this.id = id;
};
public String getId(){
return this.id;
}
public String getRoot(){
return this.root;
}
}
// use it like this
String root = Helper.fromInterfaceClass(MyInterface1.class).getRoot();