This site requires JavaScript, please enable it in your browser!
Greenfoot back
Julian
Julian wrote ...

2012/5/8

Invoking a Method

Julian Julian

2012/5/8

#
I have a Class “Button”, it takes a string in its Constructor, and it has a Method “playPhoneme”. I instance an object “a”, I can add the “a” object to the world and when the mouse clicks on it the “playPhoneme” method runs. If I instance the “a” object and add it to the world inside an “if” block I can action the “playPhoneme” inside the “if” block, but I cannot action the “a.playPhoneme” method outside the “if” block. i.e. . if (firstPass){ . Button a = new Button("a"); . addObject(a, 63, 76); . a.playPhoneme(); . firstPass = false; . } . a.playPhoneme(); The compiler throughs “cannot find symbol - variable a” How do I access an object created inside an “if” block, from outside the “if” block? Regards Julian
danpost danpost

2012/5/8

#
I am wondering...this is obviously in your world class, but where in that class? Is the code part of the world's act method (and if so, should it really be there)? Can you show the world class code?
davmac davmac

2012/5/8

#
You could declare it outside the "if" block:
Button a = null;
if (firstPass) {
    a = new Button("a"); 
    addObject(a, 63, 76);
    a.playPhoneme(); 
    firstPass = false;
}
a.playPhoneme();
However, the problem then is that 'a' might be null, so you will get an error at run time. Perhaps the real solution is to remove the 'a.playPhoneme()' call outside the block - after all, there's only two possible cases: 1) firstPass == true, you created the button, and already called playPhoneme on it 2) firstPass == false, you didn't create the button, and so it doesn't make sense to call playPhoneme
davmac davmac

2012/5/8

#
On further thought, I think what you really wanted to do was make 'a' an instance variable, outside the method altogether:
public class SomeClass
{
    Button a;

    ...
}
Then change your code above to:
    if (firstPass) {  
        a = new Button("a");   
        addObject(a, 63, 76);  
        firstPass = false;  
    }
    a.playPhoneme();  
This will create the Button once, and then call playPhoneme() on it continuously.
Julian Julian

2012/5/9

#
Thank you for your responses. I simplified the problem to more concisely define my difficulty. If I instance a new object in any type of structure, I cannot invoke its methods outside the structure. I have instanced “Button” objects from within the World’s Constructor, from another method, and even (as I showed) in an “if” block. You are right, the “if” block is in the World’s “act()” method, but even if I instance “Buttons” in the World’s Constructor I still cannot invoke the methods in the World’s “act()” method. It is not what I what, but if the “if” line and it closing bracket are commented out, the “a.playPhoneme()” method is activated twice. Or more precisely, the compiler does not through an error on the second “a.playPhoneme()”. i.e. . //if (firstPass){ . Button a = new Button("a"); . addObject(a, 63, 76); . a.playPhoneme(); . firstPass = false; . //} . a.playPhoneme(); I do not what to call the “a.playPhoneme()” twice. I simply included it to show that the exact same line of code works inside the block but not outside the block. So the commented out block compiles and runs. But the original example will not compile. When this is compiled, the second “a.playPhoneme()” generates the compile-time error “cannot find symbol - variable a” . if (firstPass){ . Button a = new Button("a"); . addObject(a, 63, 76); . a.playPhoneme(); . firstPass = false; . } . a.playPhoneme(); This makes no sense to me. Is the compiler wrong to complain that the “a” is an unknown symbol? It is almost as if the scope of the “a” object is local to the block. But, as far as I know, an object created in the method of an object (e.g. the Constructor of a World) it is available to all other methods in that object’s methods e.g. “act()”. Thank you for your help, this has been driving me potty. Regards Julian
davmac davmac

2012/5/9

#
This makes no sense to me. Is the compiler wrong to complain that the “a” is an unknown symbol?
No, the compiler is perfectly correct. If you define a local variable inside a block, it doesn't exist outside the block.
It is almost as if the scope of the “a” object is local to the block
That's exactly the case.
But, as far as I know, an object created in the method of an object (e.g. the Constructor of a World) it is available to all other methods in that object’s methods e.g. “act()”
That's not correct. For example, this doesn't compile:
class A extends Actor
{
    public A()
    {
        int a = 4;
    }
    
    public void act()
    {
        int b = a;
    }
}
Julian Julian

2012/5/10

#
Thank you that makes sence. How then do I Instance an object in the World's Constructor and Invoke a Method of that object in the World's "act()" Method? At the moment each "button" object Invokes its own "playPhoneme" as part of its "act()" Method when the mouse clicks on it. I now wish to be able to Invoke the "playPhoneme" Method for each "button" object when specific keys are pressed. The obvious place for a keyboard-handler is in the "world" object's "act()" Method. And there is my problem. If I Instance all the "button" objects in the "world" object's Constructor how do I Invoke a specific "button" object's "playPhoneme" method from the "world" object's "act()" Method? This seems to be a reasonable thing to be able to do. After all the objects Instanced in the World's Constructor exists as entities in the Greenfoot simulation. Surely it should be possible for one object to Invoke the Methods of another object. So in this case: as the "world" object's Contructor Instanced the "button" objects, it seems reasonable for the "world" object's "act()" Method to be able to Invoke any of the "button" objects' Methods. Another way to create a keyboard-handler would be to code the "Button" class with a bank of "if" statments to see if a sepecific "button" object is to Invoke its "playPhoneme" Method when its key is pressed. But this seems incredibly waistfull on processor time to have each "button" object work its way through at least 44 "if" statments. Again Thank you for your help and clear explanations. Regards Julian.
davmac davmac

2012/5/10

#
How then do I Instance an object in the World's Constructor and Invoke a Method of that object in the World's "act()" Method?
You use an instance variable. To modify the example above, you would do:
    class A extends Actor  
    {
        private int a;  // instance variable! available to all (non-static) methods in this class
        public A()  
        {  
            a = 4;  
        }  
          
        public void act()  
        {  
            int b = a;  
        }  
    }
(The example uses 'int', but you can use object types just as well).
Julian Julian

2012/5/10

#
Thank you Davmac, I am a little embarrassed. You have pointed out the blatantly obvious. I have implemented what you pointed out and all works well. Thank You. I learnt to program a long time ago, before OOPs languages where so ubiquitous. I feel I understand the concepts of OOP: Classes, Instancing, Invoking, Inheritance, Encapsulation, Overloading, Objects, … And I understand the concept of the Scope of a variable. But I am finding it hard to get rid of the idea of subroutines. Methods are a bit like subroutines but the Objects Instanced from a Class are not. I find it very easily to visualize a Procedural program, but I just can’t crowbar in to my brain a vision of an OOPs program. But I believe this is a common problem for Procedural programmer. If one first learns OOPs, it is easier to move over to Procedural programming. But many Procedural programmers can find it hard to move of to OOPs. I think this may be because OOPs uses the ideas of Procedural structures within Method. So OOPs programmers simply have to stop using OOPs concepts to move over to Procedural programming. Whereas Procedural programmers have to become familial with a whole new set of concepts and to not imprint Procedural ideas on similar, but inherently different, OOPs concepts Regards Julian
davmac davmac

2012/5/10

#
When I was learning OOP (after first learning procedural programming) I found it helpful to think of instance methods as having a hidden first parameter, which was the target object, or 'this' in Java-speak. The parameter isn't declared but it is implicitly present in any instance method. Of course, you are able to access fields and methods of this parameter without qualifying them with an object reference (because 'this' becomes an implicit target reference for anything which can't otherwise be resolved). In my head, expressions such as: someObject.someMethod(3, 4); Became: someMethod(someObject, 3, 4); ... which I understood much better. Equivalently, declarations such as: void someMethod(int a, int b) { } when declared inside 'SomeClass' could be thought of as: void someMethod(SomeClass this, int a, int b) { } That is, I recognized the existence of a hidden 'this' parameter. Having done this translation, a class just becomes a data type with a set of methods which operate on it. Of course inheritance (and method overriding) requires some further mental acrobatics, but even that can be reduced to procedural terms. Maybe this will help you too. Good luck, Davin
You need to login to post a reply.