Edit: Have edited to provide more spefic code
As you can see my sprite drawing is breaking this rule.
I would be really grateful if someone could explain by way of pseudo code based on my code below (This is because I've read many explanations of this rule but I still don't really understand why it's a problem or how to do what I need to do without breaking this rule :-( )
1) Why would this cause a problem in my code?
&
2) Please explain an alternative way of doing what I'm attempting to do (while keeping a separate resource class that is specifically for loading my resources and creating my sprite objects).
Is there anything wrong with accessing objects through 2 or more class objects. I will explain through some code:
Here I have 3 classes, is there anything wrong with accessing the method from class2 through another object as in the third class below..........:
Code
My Resource Class
//Resource class
public Class Resource(){
Bitmap myTexture;
Quad mySprite;
public void LoadResources(){
//Load graphics
myTexture = BitmapFactory.decodeResource(view.getResources(), R.drawable.myBitmap);
//Create my objects
mySprite = new Quad(); //Create new Quad object
mySprite.setTexture(myTexture); //Set texture to this quad
mySprite.setSize(100,100); //Set size of this quad
}
}
My Quad Class
public class Quad(){
//This custom class has the bulk of the code to create all of the Quads / Sprites
public void setTexture(Bitmap textre){
//etc.....
}
//etc....
}
public void draw(int x, int y){
//Draw code here
}
And finally, my main GLRenderer class:
public class MyGLRenderer implements GLSurfaceView.Renderer{
Resource res;
public MyGLRenderer(){
res = new Resources(); //Create object to my resources
}
public voide onDrawFrame(){
//Here is my main loop and I need to draw my sprites here, so........
res.mySprite.draw(x, y); //Draw my sprite
}
Why it's bad to have several chained method calls
The law this violates
This violates a coding practice known as the law of demeter. This law states that you should only talk to those classes "next to you".
Why this is a bad thing
The reason for this is because, by calling methods in several other classes, your class needs to know about those methods, and depends on those methods changing. This is called close coupling. If the methods change, you need to change lots of code in other classes. This is called "Shotgun Surgery" and isn't a desirable feature in a program!
A possible solution
Look into the proxy design pattern. It's primarily designed to provide an interface to another class, and it might help you here. Perhaps by having a reference to both objects, this class can provide a common interface for all methods to talk via and reduce the coupling between the classes.
Edit to help with your example
Your example isn't actually that bad. You get an object, and you make a method call on it. The dependency comes in one form: If you remove the mySprite field from your class, your code won't work, and if you remove the draw method from your sprit it won't work. To me, the easiest solution is to add a Proxy method to your Resources class, called draw() that accepts a sprite as an argument.
Secondly, perhaps instead of accessing mySprite directly, you can put it through a method. Let's say you had a member that looked like this:
private ArrayList<Quad> sprites = new ArrayList<Quad>();
This means that in order to gain access to these sprites from the outside, you would need to have some sort of method. Now, by forcing other classes to talk via these methods, you're reducing coupling. This is because the original class only needs to know the one method in another class, and the other class will do the work. Then you wrote a drawSprite method that looked something like:
public void drawSprite(int index) // Index really is up to you {
sprites.get(x).draw();
}
Now I know it might have more parameters than that, but it only means one method call from your MyGLRenderer class, hence conforming to the law of demeter, and reducing coupling in your classes.
Sorry, but it wouldn't work...
As Mike pointed out, Classes instantiated in any of SomeClass's methods are "alive"/valid only when you're inside the method. This means that the instantiated object is specific to the method, and can't be accessed outside the method.
A possible solution:
The solution to this is to add a SomeClass2 member to SomeClass. If you instantiate this member in SomeClass's constructor, it'll stay alive till SomeClass is in scope, making it available for you to use. The code would look something like this:
SomeClass:
class SomeClass
{
// Define the class attributes. This class can be then accessed publicly
SomeClass2 class2
// Constructor - Instantiate all your members here
public SomeClass()
{
// Instantiate class2 in the constructor
this.class2 = new SomeClass2();
}
// Your method which does what you need
public void classMethod()
{
class2Object.class2Method();
}
}
SomeClass2 will stay the same
And SomeClass3 will be:
class SomeClass3
{
public void class3Method()
{
SomeClass classObject = new SomeClass();
// Call the instantiated member and then call it's method
classObject.class2.class2Method();
}
}
This should compile/run. I would comment on the design, but I'll wait to find out what you're planning to use this for before I do! :)
It will work (except you your SomeClass2 object is declared within the method, and it should be within the class as a member variable, but I assume that's a typo).
But I would consider using getters and setters instead (it's considered better practice):
class SomeClass{
private SomeClass2 class2Object = new someClass2();
public SomeClass2 getClass2Object() { return class2Object; }
}
class SomeClass2{
public void class2Method(){
//Some code here
}
}
SomeClass3{
public void class3Method(){
SomeClass classObject = new SomeClass();
classObject.getClass2Object().class2Method();
}
}
Related
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.
I'm implementing a visitor pattern for a particular domain, where I have some BaseVisitor, ie:
public class BaseVisitor {
someC someInstance;
visitA(...) {
...
}
visitB(...) {
...
}
}
and a class that changes one particular functionality, ExtendedVisitor, ie:
public class ExtendedVisitor extends BaseVisitor {
visitA(...) {
...
}
}
This ExtendedVisitor has a different implementation of visitA.
What I want to do is that when I'm in visitB of BaseVisitor, in special case I want to use the method of the ExtendedVisitor (visitA) as opposed to the regular visitA of the BaseVisitor itself. This works fine, ie.:
visitB(...) {
if (...)
new ExtendedVisitor().visitA();
else
visitA();
}
Now obviously, in the BaseVisitor there are many visit methods, and so the visitA of ExtendedVisitor will call them (ie. the original implementation of those methods - in BaseVisitor). The problem is that at this point I lost the instance of someInstance (ie. it is null). Is there a way for the two classes to share the variables? Ie. let the child use parent's variables?
Since you are calling to new ExtendedVisitor() you are creating a new instance of that class and of course someInstance will be null. You could create a constructor like
public ExtendedVisitor(someC someInstance ){
this.someInstance = someInstance
}
But it doesn't sound a great idea...
With your design you are forcing your parent class to know the functionality of its children classes. I see a coupling issue here. Probably you should rethink your code and use inheritance and polimorfism in a better way.
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.
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.
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.