Polymorphism with Static Methods - java

I'm creating a Mario clone where everything on the screen is an instance of ScreenElement. A ScreenElement is Landable if it can be landed on by Mario.
public class ScreenElement {
public boolean isLandable() {
return false;
}
}
Some classes override isLandable, for example:
public class GrassBlock extends ScreenElement {
#Override
public boolean isLandable() {
return true;
}
}
And classes that don't override isLandable should inherit it from the closest super class that does. That is to say, I need polymorphism.
Now this all works fine as long as isLandable is an instance method. However whether or not a given ScreenElement is Landable depends on the class, not the instance. So isLandable should really be static. But if I make it static, I cannot override it or inherit in sub classes that don't explicitly define it. Is there a simple workaround to this problem.
EDIT:
I do realize that the way I have it set up right now, it is working correctly but the reason I am bringing this up is because I have encountered a problem. Given a class that extends ScreenElement, I need to find out the result of isLandable. The only thing I could think of was this:
private <S extends ScreenElement> boolean isThisLandable(Class<S> category) {
return category.newInstance().isLandable();
}
I have to create a new instance to figure out something that doesn't depend on the instance, and this seems unnatural.
EDIT 2: Here's the specific piece of code that I'm dealing with.
private <S extends ScreenElement> S getGenericScreenElement(Mario mario, Class<S> category) {
for (ScreenElement element : screenElements) {
if (category.isInstance(element)) {
S elementToTest = category.cast(element);
if (elementToTest.isLandable()) {
//return elementToTest if it matches additional criteria
}
}
}
return null;
}

You're overthinking this.
In a nutshell, this code is doing exactly what you want it to do.
Here's what happens.
Your parent class, ScreenElement, defines by the isLandable() method by default, and it is always set to return false. By creating a new class that is a ScreenElement, if they wish to change this behavior, they must override that method to do so.
The fact that your GrassBlock does override this method is indicative that any instance of a GrassBlock will register true if its isLandable() property is checked.
With your code revision, you're still overthinking this.
All you need to do when you attempt to use an instance of ScreenElement - be that an instance of ScreenElement or any of its children - is to just call the method.
You shouldn't care about that property until you decide to check it, during its run. The way you're checking it now makes very little sense at all.
As an example:
ScreenElement vanillaElement = new ScreenElement();
GrassBlock block = new GrassBlock();
System.out.println(vanillaElement.isLandable()); // will print false
System.out.println(block.isLandable()); // will print true
More explicitly, with your sample code, you can greatly reduce it. Many of your statements to check against the type are unnecessary, especially when casting. You're guaranteed to have nothing more than a ScreenElement, and since isLandable() is defined on at least that, you will never run into a scenario in which you cannot call that method.
The above will turn your code into this. I leave the addition of your Mario parameter up to you since its purpose is unclear in this method.
private ScreenElement getGenericScreenElement(Mario mario) {
for (ScreenElement element : screenElements) {
if (element.isLandable()) {
//return element if it matches additional criteria
}
}
return null;
}

The fact that you need the methods to be overrideable and you want to do polymorphic dispatching means that they should not be static methods.
However whether or not a given ScreenElement is Landable depends on the class, not the instance.
So make the methods instance methods without using the instance state.

Related

How to store static data about a class to

Imagine I have an abstract class like this:
public abstract class Device {
public Device(DeviceModel model){
// ...
}
public abstract boolean isBuildable();
}
Then I have an implementation of it that might look like this:
public final class Floor extends Device {
// ...
#Override
public void boolean isBuildable(){
return false;
}
}
Here, each Device subclass returns either true or false to #isBuildable(). But each instance of Floor always returns false. Another implementation of Device may return true. That sounds like a static data : it does not depends on the current instance, but on the type of the Device.
Currently, I'm creating an instance of the class to get its value, as #isBuildable() isn't static. But I think that's poor code design.
So, what I'm trying to achieve here is like creating abstract static method. I've seen this question that doesn't help so much. I would forces the implementation of #isBuildable (this time as static) in all subclasses of Device, so that I can invoke Floor.isBuildable() or something else of the same kind.
Here I can't control all the source, so I can't use reflectivity on that.
Hope you understand this weird question !
If you need to store class-specific (not instance-specific) information, custom annotations may be the way to go.
This require a function using reflection to access that piece of information, which could be overkill in a small project, but should be no problem in a larger framework or similar project.
In Java, static methods cannot override other static methods, so what you want to do is not possible.
Since Java has no real type variables (the type variables used for generics do not survive until run time) you would need an instance anyway to determine which overridden static method to call.
Suppose you have a class Device with two subclasses, Floor and Ceiling, all of which have a method called foo(). Since there are no run-time type variables, T.foo() cannot work, and Device.foo(), Floor.foo() and Ceiling.foo() all specify exactly which method to call.
There are a few solutions/workarounds:
Call the right method through reflection. You will lose any static type checking.
Introduce a companion enum or class which contains the information about your types. For example:
public class DeviceType {
private final boolean buildable;
private DeviceType(boolean buildable) {
this.buildable = buildable;
}
public boolean isBuildable() {
return buildable;
}
}
public class Floor extends Device {
public static final DeviceType DEVICE_TYPE = new DeviceType(false);
...
}
Now you can pass around Floor.DEVICE_TYPE as a kind of representation of the class which contains the information you want.

Why is subclass field initialized to its default value within super constructor? [duplicate]

I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.
I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:
class Foo extends BaseClass
{
private final String bar = "fooBar!";
public Foo()
{
super();
}
#Override
public void initialize()
{
System.out.println(bar);
}
}
And the base class:
abstract class BaseClass
{
public BaseClass()
{
initialize();
}
public abstract void initialize();
}
In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!
Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?
Thanks for any insight!
The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.
The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.
Generally though, it's bad practice to call overridable methods from a constructor.
It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.
See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields
Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.
There's just one thing I would like to add to the accepted answer, because I don't entirely agree with his conclusion.
We've all done this.
class Engine {
public Engine() {
init();
}
void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
...
}
Now the question is, which access modifier should we add to our init() function. Should it be private or protected.
make it private <-- keeps subclasses out
make it protected <-- allows subclasses in
Before you make a choice
Now first of all, you should realize that (almost) all code in the Engine class can be replaced by a subclass.
code in a public function, can easily be overridden
code in a protected function, can easily be overridden
code in a private function, can be replaced by overriding all methods that call it.
Well, there is just one exception:
you can never modify the code of a constructor
you can never avoid a private method being called from the constructor of a super class.
(and of course, you cannot replace a final method)
Protected init() - the wrong way
Let's say the init() method is protected there is indeed a pitfall. It is tempting to override it to add features as follows. That would indeed be a mistake.
class SubEngine extends Engine {
int screws = 5;
void init() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this won't print 5, but it will print 0.
System.out.println("tightening " + screws + " screws");
}
}
Protected init() - the right way
So, basically, you should just disable the parents code and postpone execution to your own constructor instead.
class SubEngine extends Engine {
int screws = 5;
public SubEngine() {
initSubEngine();
}
void init() {
// disable parent code
}
void initSubEngine() {
tightenScrews();
super.init();
}
void tightenScrews() {
// this will print 5 as expected
System.out.println("tightening " + screws + " screws");
}
}
Private init() - you may need a phonecall
Now, what if the init() method is private ?
Like mentioned above, there is no way to disable the code of a parent constructor. And if init() is private you simply cannot disable it.
You'll end up copying the entire Engine class, perhaps just to add 1 line of code.
And that may not be the end of it. Even after copying your class, your copied object won't be an Engine meaning that you won't be able to use your EngineUtil#inspectEngine(Engine engine) function.
Perhaps somebody knew this in advance and made an IEngine interface. Then you can get away with it.
In practice it means you'll have to take your phone, and call to that other department that made the Engine class, and ask them to change their code a little to take away some restrictions.
Intelligent design
There is another way. Constructors are for setting variables. They shouldn't activate anything. Everytime you see a class creating a new Thread from their constructor (or through a private method) that should be a red flag.
class Engine {
public Engine() {
}
public void init() {
lockDoors();
releasePressure();
tightenSeatbelts();
launchRocket();
}
// and you probably also want one of these
public void shutdown() { ... }
...
}
Intention
Of course, your intention may very well be not to open up your code. Perhaps you really don't want to allow others to extend your classes. There certainly can be cases where you want to lock people out.
Be aware that it will also make it harder to write tests for your code.
Anyway that's a different scenario.

How to prevent sublasses from default implementing a method of super class?

I have a method which adds Objects to an static list like this:
#PostConstruct
protected void registerToTransactionList() {
TransactionValidator.registerTransactionList(this);
}
registerTransactionList method just adds "this" to the static list, this method is in BalanceTransactionValidator class which extends TransactionValidator (owner of static list),the problem is all subclasses of BalanceTransactionValidator class are added to static list either,and if I override registerToTransactionList method in them like this:
#Override
#PostConstruct
protected void registerToTransactionList() {
}
It doesn't add subclasses but doesn't add BalanceTransactionValidator either. Can anybody help me on this? Please notice sublasses are overriding this method by default.
make the method private to block the visibility
private void registerToTransactionList() {
}
or make the method final to block it from been override
protected final void registerToTransactionList() {
}
There are two ways of achieving that:
Keep your method as it is; but then you have to actively check for the type of your objects before externally calling that method
Change your whole logic and make that method private
It won't help to make the method final as suggested in one of the comments - your problem is not that subclasses are overwriting that method; in essence, you have a design problem: you wish that subclasses should not invoke that method at all.
So, the only real option that makes sense here is "2.". You see, by having public method on a class that you want to be extended you are implicitly saying: it is perfectly fine to call that method; on any object that is instance of the base class (or child class!).
And in your case, that is not true: you actually do not want that the code behind this method runs for child classes. Then you shouldn't put that method in the list of public/protected methods of your base class!
Finally: you might want to step back and do some reading about good OO design. Class hierarchies do not fall from the sky: you willfully design them for a certain purpose. In other words: there is more to inheritance than just putting some "A extends B" on your class declaration. You have to understand each and every method on your B class; and how your child classes should deal with them!
EDIT: after some more thinking, I guess you are doing things "the wrong way", like:
class BaseClass {
public final void doRegistration() {
BaseClass toRegister = getObjectForRegistration();
if (toRegister != null) { ... register toRegister ...
}
protected BaseClass getObjectForRegistration() {
return null;
}
With that code, you could then put
protected BaseClass getObjectForRegistration() {
if (this instanceof ClassThatShouldBeRegistered) {
return this;
}
return null;
}
into that one class that wants to be registered. Probably there could be even nicer ways of doing so; but after some thinking I don't see how we could avoid the instanceof. But the above code should work; and it only requires specific code only in your base class and in that one class that wants to register something.

Questions on classes extending from a base class (Java)

I'm a beginner in Java trying to write a system of party quests for a game that I'm currently writing and I have a few questions I'd like to be answered. I've already gone around and asked other people, but they're not familiar in Java.
In the past I'd tried making a bunch of classes and accessing them with multiple get methods. I found that incredibly tedious to write and thought I could unify them under an abstract class/implemented class. Thus, the code looked more like this ...
DynastyPQInterface pq = new CustomPQ // or ....
DynastyPQInterface pq = new OtherCustomPQ
Of course, this presented difficulties such as being only able to use implemented methods. It didn't allow me to access the class' exclusive methods that I might want to use later on.
Ultimately, what I want to do is to be able to use a single get method to return any of these derived classes, but still retain the ability to just universally use the get method to call methods that they have in common, such as execute, create, end, while simultaneously allowing me to reach out to their exclusive methods specifically. Is there a way to do that, or is it impossible?
If it's still not clear ...
The code I have write now is a base class that is extended to the other classes in the manner ...
DynastyPQ (base) -> methods include (run(), execute(), end())
CustomAPQ (inherited from DynastyPQ) -> (has exclusive methods like getPoints())
CustomBPQ (inherited from DynastyPQ) -> (has exclusive methods like revivePlayer())
I want to write a get method so to rid myself of multiple. What I have right now is ...
DynastyPQ dynastyPQ;
DynastyPQ getPQ() {
return dynastyPQ;
}
void setPQ(DynastyPQ pq) {
dynastyPQ = pq;
}
Doing this ...
DynastyPQ pq = new CarnivalPQ();
I can only access DynastyPQ's methods rather than Carnival's methods.
Is there a way to access the exclusive methods while universally being able to execute the four base functions without regard to the type of class, or did I miss something earlier?
tl;dr -> I want one get method that universally returns all classes that inherit from class X; however, I want to be able to access each class's exclusive methods.
You can probably just cast the object to the derived class:
DynastyPQ pq = new CustomAPQ();
((CustomAPQ)pq).customAPQmethod();
If you don't know what is the dynamic type (the type you used after the new operator), you can use the instanceof keyword:
DynastyPQ pq = getPQ();
if (pq instanceof CustomAPQ) {
CustomAPQ a = (CustomAPQ)pq;
a.customAPQmethod();
} else if (pq instanceof CustomBPQ) {
CustomBPQ b = (CustomBPQ)pq;
b.customBPQmethod();
} else {
// Neither a CustomAPQ nor a CustomBPQ.
}
If you don't want to do that, you can use polymorphism:
class DynastyPQ {
final void run() {
// code.
}
final void execute() {
// code.
}
final void create() {
// code.
}
void specific1() {}
void specific2() {}
}
class CustomAPQ extends DynastyPQ {
#Override
void specific1() {
// do stuff specific to CustomAPQ.
}
#Override
void specific2() {
// do stuff specific to CustomAPQ.
}
}
class CustomBPQ extends DynastyPQ {
#Override
void specific1() {
// do stuff specific to CustomBPQ.
}
#Override
void specific2() {
// do stuff specific to CustomBPQ.
}
}
Now, you can do:
DynastyPQ pq = new CustomAPQ();
pq.specific1();
The called method will be CustomAPQ::specific1(). If specific1() was not declared in CustomAPQ, then, it will just do nothing.
Other than #CelineNOEL suggested it is not possible. Because you declared a class of type DynastyPQ, you can call only methods defined inside that class. In the moment you want to call specific method, not shared one, you know from which class it is and you can use casting to call that specific method.
((CustomAPQ)pq).customAPQmethod()
Shared methods you are using in code, when you don't know which class should execute same peace of code(or you want it to execute it different if you override share methods in every sub-class), and you delegate it to be resolved in runtime. So reconsider your design and in base class put methods that needs to be called dynamically. All other methods you are sure are specific for one class put only in that class. On that way your code will be cleaner and you will not mess thing that should be separated.

Java - Restricting by what a method can be called

I have methods set to public because they must be called by an exterior class, but I only ever want them called by one or two methods. Being called by other methods could create bugs in my program. So, in order to prevent me from accidentally programming around my own methods, I have been doing stuff like this within the methods of which I want to restrict callers:
if(trace.length<2){
throw new Exception("Class should not call its own function.");
}else if(trace[1].getClassName()!=desiredClassName || trace[1].getMethodName()!=desiredMethodName){
throw new Exception(trace[1].getClassName()+"\" is invalid function caller. Should only be called by "+desiredClassName+"->"+desiredMethodName+".");
}
Is there something else I should be doing, or should I just not forget how my program works?
You should be using visibility to restrict calling - making a method public (or for that matter, javadocing it) is not going to work unless you have dicipline (and you control the callers too). From your description, you are neither.
What you can do is make the class package private, and put it in the same package as the two callers of that class. As long as you have a proper package structure, this can work. E.g.:
Your class that should only be called by A and B:
package thepackage.of.a.and.b;
//imports here
class CallableByAB {
public void methodA(){}
public void methodB(){}
}
A:
package thepackage.of.a.and.b;
public class A {
/*...other code here */
new CallableByAB().methodA();
/*...other code here */
}
B:
package thepackage.of.a.and.b;
public class B {
/*...other code here */
new CallableByAB().methodB();
/*...other code here */
}
other classes cannot call new CallableByAB() or import it. hence, safety.
This seems like a very brittle solution to a problem you should not need to solve.
In this particular case you may not suffer too greatly in future maintenance, just a couple of methods with these kind of special guards. But imagine trying to apply such logic to many methods across a large code base - it's just not a tenable thing to do. Even in your case you are effectivley writing code that cannot be reused in other contexts.
The fact that you need to do this surely reflects some kind of mis-design.
I infer that you have some kind of stateful interface whose state gets fouled up if called unexpectedly. Ideally I would want to make the interface more robust, but if that just cannot be done: If there are particular methods that should use this interface can you move those methods to a specific class - maybe an inner class of the current objtec you have - and have a handle visible only in this class?
private Class TheLegalCaller {
private RestrictedCallee myCallee = new RestricatedCallee() ; // or other creation
public void doOneThing() { myCallee.doOne(); }
public void doOtherThing() } myCallee.doOther(); }
}
Now the downside with this is that it only pushes the problem up a level, if you randomly use TheLegalCaller in the wrong places then I guess you still have an issue. But maybe by making the restriction very visible it aids your memory?
Try using access rules.
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/90c424dc44db523e
I found a very simple way to do that, but requires some coding methodology:
class AllowedCaller {
private Object key;
public boolean getKey(){
return key;
}
public void allowedCallingMethod(RestrictedAccessClass rac){
this.key = rac;
rac.restrictedMethod();
this.key = null;
}
}
class RestrictedAccessClass{
public void restrictedMethod(){
if(allowedCallerInstance.getKey() != this){
throw new NullPointerException("forbidden!");
}
// do restricted stuff
}
}
I think it could be improved to prevent multithread simultaneous access to restrictedMethod().
Also, the key could be on another class other than AllowedCaller (so RestrictedAccessClass would not need to know about AllowedClass), and such control could be centralized, so instead of a single key, it could be an ArrayList with several object keys allowed at the same time.

Categories