Design pattern needed for enforcing static methods - java

Okay, I want to start off my question with an example of what I'd basically like to do, though it's not working this way.
I want to have an interface IDog that enforces its implementations to have some methods. I also want an superclass AbstractDog implements IDog to give basic attributes and methods to all Dog classes. Then I want to have Subclasses like Poodle extends AbstractDog. My problem here are static methods - I basically want each subclass of AbstractDog to have a different static method but I want to be able to enforce this method from IDog.
So my naïve (and wrong) implementation would be:
public interface IDog {
String getName(); // every dog instance should be able to call name
static String getDescription(); // every dog class should be able to get its description
}
public abstract class AbstractDog implements IDog {
private String name; // every dog instance will have this
public AbstractDog(String name) {
this.name = name;
}
#Override
public String getName() {
return this.name; // every dog instance can call this
}
}
public class Poodle extends AbstractDog {
private static String description = "It's a poodle!"; // all Poodles have the same description
public Poodle(String name) {
super(name);
}
#Override // from IDog
public static String getDescription() {
return description;
}
}
Now, as I said, this is not correct because the AbstractDog class would need a static abstract method getDescription() and IDog needs an implementation of its method and it can't be overridden.
I want to know, if there is a Design pattern which matches my problem: enforcing a set of classes (which could or should have an intermediate superclass) to implement a (different!) static method.
One possibility I have discovered, but I'm not sure if it may be useful or even adequate, would be the use of an enum DogType and then just having a class Dog with a DogType attribute:
public enum DogType {
Poodle("This is a poodle."), Havanese("This is a Havanese.)";
private String description;
private DogType(String description) {
this.description = description;
}
public String getDescription() {
return this.description;
}
}
public class Dog {
private String name;
private DogType dogType;
public Dog(String name, DogType dogType) {
this.name = name;
this.dogType = dogType;
}
public String getName() {
return this.name;
}
public String getDescription {
return this.dogType.getDescription();
}
}
However, this "workaround" loses an ability over my initial idea: I now can't additional functionalities to only one dog class like an instance method void prance() which should only be accessible to Poodle.
Many topics regarding similar questions have refered to the Factory pattern, but I'm not sure how it fits my problem because I don't necessarily need a constructing method. And as the number of dog races rises my code would become very confusing I think. Or maybe I just didn't get how the Factory should be used correctly in my case.

Interfaces are enforced behaviours. Classes are used to specify properties. Static methods get hidden. They are not over-ridden by subclasses. So if you have static methods in your subclasses, but your object reference is of supertype class, then your static method from superclass is invoked. This is class Method hiding, happens with static methods.
I want to know, if there is a Design pattern which matches my problem:
enforcing a set of classes (which could or should have an intermediate
superclass) to implement a (different!) static method.
Sorry. Static methods and inheritance don't go hand in hand.
I now can't additional functionalities to only one dog class like an
instance method void prance() which should only be accessible to
Poodle.
You could introduce a interface Prancable with method void prance().
public interface Prancable{
void prance();
}
public class Poodle extends Dog implements Prancable{
#Override
public void prance(){
System.out.println("My Poodle can prance.");
}
}
You can proceed in this manner for specific methods that add behaviour to different dog breeds.

This is a code smell, there is likely a better way to do it.
If the static method will always return the same thing for all objects of the class, you should just make it a regular get method.
#Override \\ from IDog
public String getDescription() {
return "This is a poodle";
}
If the static variable may be changed then make a new object that holds this class-wide state and give it to each class in the constructor.
ex.
// StringState is a new class that holds a string and has a set and get method
StringState desc = new StringState("original description");
IDog dog1 = new Poodle(desc);
IDog dog2 = new Poodle(desc);
// prints original description
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());
desc.set("New description");
// prints new description, since both objects share the same
// StringState,changing it here changes it in all of them.
System.out.Println(dog1.getDescription());
System.out.Println(dog2.getDescription());

Related

Java Abstraction and Interfaces

It's been a rather long time since I've messed around with Java Abstraction and/or Interfaces, but I'm coming back to it now for a project and something is getting on my nerves. Below is a snippet of my code.
public class A {
private static String name = "None";
private static String description = "No description";
public A() {}
public A(User user) {
user.setData(this);
}
public static String getName() {
return name;
}
public static String getDescription() {
return description;
}
}
public class B extends A {
private static String name = "B";
private static String description = "This is B";
public B() {}
public B(User user) {
super(user);
}
}
public class User {
private A a;
public void setData(A a) {
this.a = a;
}
public A getData() {
return a;
}
}
When I use B.getName() I expect it to return "B" but it's instead returning "None".
Now I'm obviously doing something wrong, and searching around didn't help a bit. I'm fairly positive that this is possible someway, unless I'm getting confused with another language.
Could someone please point me in the right direction? Thanks.
You called the getName method on the class B. B doesn't have a static method called getName, so it looks for it in the superclass, A, which does.
Maybe you expect B's version of name to override A's? Variables don't get overridden. A is accessing the static variable name defined on A, that the method was originally called on B doesn't affect that.
Inheritance and static methods don't work well together. OO concepts like polymorphism rely on runtime dispatching, the word static should imply the opposite of that. With polymorphism the program works at a high level of abstraction, referring to the objects by a super type and letting the subclasses work out the details. With static methods you have to refer to the specific subclass you want the method called on, so you don't have that level of abstraction.
Welcome back to Java again.
You are using static variable in class A and B. These variables are associated with class instead of the objects.
If you change your method to get name from the User, it will work as you are expecting.
You need to override the method getName():
public class B extends A {
private static String name = "B";
private static String description = "This is B";
public B() {}
#Override
public static String getName() {
return name;
}
public B(User user) {
super(user);
}
}
The problem you are facing lies in the definition of the methods getName and getDescription: They are defined in class A as static members. This means that even when calling B.getName() the actual call is A.getName() and there the static member variable value of name is set to None.
When thinking about inheritance you have be careful what you declare as static. This has nothing to do with Interfaces or abstract classes.
public class A {
protected String name = "None";
protected String description = "No description";
public A() {}
public A(User user) {
user.setData(this);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}
public class B extends A {
public B() {
name = "B";
description = "This is B"
}
public B(User user) {
super(user);
}
}
public class User {
private A a;
public void setData(A a) {
this.a = a;
}
public A getData() {
return a;
}
}
With the protected keyword you can access the fields from the extending class.
See also:
http://www.javatpoint.com/static-keyword-in-java
https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
A couple of things to note in your class :
name and description are static variables in both A and B
getName is a static method in A
static variables are bound to the class and static methods can't be overridden
This is the expected behavior since getName() method of class A has access to member variable of its own class that is "name" of class A. It is NOT because of name is static even if you make it non-static and you access it as shown in below code snippet it would return "None". Remember that only methods get overridden not member variables. So "name" of class B is not overriding "name" of class "A".
B b = new B();
System.out.println(b.getName()); --> "None" ("name" is non-static)
----------------------------------------------
System.out.println(B.getName()); --> "None" ("name" is static)
Also, if you want to get "B" as output , override getName() method of class A in class B and make method and variable non-static.

What's the point of having a constructor in an abstract class in Java? [duplicate]

This question already has answers here:
Can an abstract class have a constructor?
(22 answers)
Closed 8 years ago.
If you are never going to instantiate an object from that class, when are you going to ever use its constructor? Sorry if I come off as ignorant. I just started a class on Java at my high school.
you can initialize something in parent class , so maybe you need constructor in abstract class.
Because sub classes may use it. For example:
public abstract class Foo {
protected String name;
public Foo(String name) {
this.name = name;
}
}
public class Bar extends Foo {
public Bar(String name) {
super(name); //<-- necessary, otherwise it won't compile
}
public Bar() {
super("default name"); // <-- necessary, otherwise it won't compile
}
}
You have a constructor so subclasses can initialize the state of their parent properly.
public abstract class Parent {
private final String name;
public Parent(String n) { this.name = n; }
public String getName() { return this.name; }
}
public class Child extends Parent {
public Child(String name) { super(name); }
}
There would be no other way to initialize that private final String name attribute in the Parent without a constructor.
Well your parent class or the abstract class stores common variables throught all children classes or subclasses.
This makes it easier to store different objects (with the same parent) into collections such as and ArrayList.
It also allows you to easily manipulate and object without worrying about its details that is contained in the subclass.
You do instantiate the constructor by calling super() within the subclass.

How to access values of fields from base class?

I want to access fields of a class from base class in Java. I can do it in dot net.
see the example:
public class a{
// here I want to read the value of name or f1 or f2 or every other field values from derived classes
}
public class b extends a{
public string name;
}
public class c extends a{
public string f1;
public string f2;
}
How to do it?
You cannot read the fields your class doesn't own without explicitly naming the subclass. So, this is doable as follows:
((c)this).f1;
However, doing this would be a bad code smell: you are now tying an abstraction embodied by a to one of its specific implementations/extensions. You should better rethink your design.
An important note on code conventions
In Java it is a must that you name your classes using CamelCase and packages using lowercase, otherwise some quite bad name-resolution anomalies can happen. Not to mention any Java user getting totally lost reading your code.
You really don't want to do that as it defeats the idea of inheritance.
You can, however set up abstract functions that are implemented by derived classes. That's good programming style. Those functions can access member data in the derived and base classes.
Doing things like (i) using reflection and(ii) casting to derived classes are hacks and should be avoided. The reason being that changing a derived class should not trigger the necessity for changes in a base class.
What you should do in this case is to define abstract methods in your class a, which class b and c has to implement. You can then call these methods from a to obtain the values set by b and c.
public abstract class a{
// here I want to read the value of name or f1 or f2 or every other field values from derived classes
abstract String getName();
abstract String getF1();
abstract String getF2();
}
public class b extends a{
private String name;
#Override
public String getName() { return name; }
#Override
public String getF1() { return null; }
#Override
public String getF2() { return null; }
}
public class c extends a{
public String f1;
public String f2;
#Override
public String getName() { return null; }
#Override
public String getF1() { return f1; }
#Override
public String getF2() { return f2; }
}

Can a concrete method in an abstract class return a variable defined in the subclass?

Just as I was starting to get familiar with interfaces, I came across a stumbling block with abstract classes. In my understanding, they can be used to provide some functionality for subclasses, but forces subclasses to specify undefined functions (if there are any left).
All the examples I came across however only dealt with functionality that could have been static - no reference to instance variables.
I'm trying to hide some common functions like getName() in the abstract class, but be able to define said name in the subclass.
public interface Application {
public String getName();
}
/**
* Specify some default behaviour to keep leaf classes free of common code
*/
public abstract class DefaultApplication implements Application {
public static final String NAME = "DefApp";
#Override
public String getName() {
return NAME;
}
}
public class MyApp extends DefaultApplication {
public static final String NAME = "My App";
}
// Main class
Application myApp = new MyApp();
System.out.println(myApp.getName()); // Prints "DefApp"
I thought that protected String name might work, but this also returns the instance variable in the abstract class. Is the only solution to redefine getName() in each subclass? I wouldn't have minded so much, but this isn't the only case where I'm trying to siphon off methods into the abstract class.
Thanks!
EDIT:
if it's relevant (to suggest other approaches I could consider), Application is a plugin api, and MyApp is an example application provided. DefaultApplication is part of the base project.
You cannot override anything that's static. Static methods do not belong to a particular object, but belong to the class itself instead; when you write return NAME, the compiler reads this as return DefaultApplication.NAME.
In this case, you can either override getName() in each subclass as you already came up with, or you can make the field non-static, and do something like this:
abstract class DefaultApplication implements Application {
private final String name;
protected DefaultApplication(String name) {
this.name = name;
}
protected DefaultApplication() {
this("DefApp");
}
public String getName() {
return name;
}
}
class MyApp extends DefaultApplication {
public MyApp() {
super("My App");
}
}
This will add an extra field to every instance of DefaultApplication but as long as you don't have millions of them, that shouldn't really matter.
The annotations idea interested me, so I figured I'd throw this out here. Here's a really complicated and not exactly recommended way of printing "My App":
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
interface Application {
public String getName();
}
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#interface ApplicationName {
String value();
}
#ApplicationName("DefApp")
abstract class DefaultApplication implements Application {
#Override
public String getName() {
return getClass().getAnnotation(ApplicationName.class).value();
}
}
#ApplicationName("My App")
class MyApp extends DefaultApplication {
}
public class Main {
public static void main(String[] args) {
Application myApp = new MyApp();
System.out.println(myApp.getName());
}
}

Hiding mutators, clarification needed

Suppose you have a class Dog, that has
public class Dog {
private String name;
private double age;
// some setters
// some getters
Additionally, you have a class DogHandler, that makes an instance of the Dog d and passes it to Owner
I suppose, i can
... make a copy of a Dog before passing it to Owner, but that's an expensive operation and i'd rather avoid it.
... come up with an interface that Dog implements which contains getters only, cast Dog to that interface and pass the result along
... initialize settable variables in a constructor and simply not allow changes for this instance of an object
Are there any other ways to make sure receiver of the object cant modify it?
How do you take a simple bean containing some data and make it read-only?
This can be achieved in few ways, I can propose you 2 of them:
a) interface with getters is good idea
b) create derived class from Dog which has setters method blocked, like this:
class UnmodifiedDog extends Dog {
public UnmodifiedDog(double age, String name) {
super.setAge(age);
super.setName(name);
}
#Override
public void setAge(double age) {
throw new UnsupportedOperationException();
}
#Override
public void setName(String name) {
throw new UnsupportedOperationException();
}
}
In DogHandler:
Dog createDog() {
return new UnmodifiedDog(10, "Fido");
}
and you can pass this to the Owner:
owner.receiveDog(dogHandler.createDog());
The approaches you mention in the question are pretty much the standard steps to take to make Dog immutable. The only other tip would be to mandate that Dog cannot be overridden by declaring the class to be final.
Among the solutions mentioned here, you can also take advantage of visibility modifiers. If Dog and Owner are in separate packages, you can set the visibility of the mutators to default (package) scope or protected scope.
This will allow you to keep Dog and DogHandler in the same package (and therefore allow them both to mutate the Dog object accordingly), while keeping Owner objects separate (and therefore preventing them from making any modification to the Dog objects).
Here is an example using an interface and package access setters.
package blah.animal;
public interface Dog
{
double getAge();
String getName();
}
package blah.animal;
public class DogImpl implements Dog
{
private double age; // double seems wrong for age.
private String name;
... getters (defined by Dog interface)
// package access setters.
void setAge(double newValue)
{
age = newValue;
}
void setName(String newValue)
{
name = newValue;
}
package blah.animal;
public class DogHandler
{
public static Dog newDog(double age, String name)
{
Dog returnValue = new DogImpl();
returnValue.setAge(age);
returnValue.setName(name);
return returnValue;
}
}
package.blah.somethingelse;
public class Blam
{
private Dog myDog;
public Blam()
{
myDog = DogHandler.newDog(1.4D, "Tippy");
}
}

Categories