I know that in AS3 I can create a Main class and link it to the FLA file. I tried doing the same in AS2 but couldn't. (When I try linking the fla to a class, it says the feature only exists in AS3)
Can I link the FLA to a class in some other way? If this is not possible, how would you suggest I perform actions when the file is loaded (and, in this case, define an ExternalInterface)?
Thank you.
here is the approach i would use. you define a static method in your 'document' class and then pass in the reference to your main timeline at runtime:
class MyClass extends MovieClip
{
public static function main(target:MovieClip):Void
{
target.__proto__ = MyClass.prototype;
target.init();
}
private function init():Void
{
// your construction code....
}
}
Then in your FLA, on the first frame, invoke the class's static 'main' and pass it the main timeline movieclip as the argurment. this is kinda like wrapping the timline with your document class.
MyClass.main(this);
Example based on http://www.bit-101.com/blog/?p=857. i just added it here to fix up the broken code tags on his site.
Related
Overview
I have written a babel plugin that adds a custom constructor to classes. I also use the #babel/plugin-proposal-class-properties plugin to support class properties. My .babelrc looks like this:
{
"plugins": [
"./plugins/my-plugin.js",
"#babel/plugin-proposal-class-properties",
]
}
I'm using babel-core#7.2.2, and #babel/plugin-proposal-class-properties#7.2.3.
The issue
The class properties plugin overwrites my generated constructor. For example, given this test file:
// Source
class Test extends Base {
// someProp = 'yay';
}
If I run without the class properties plugin, my constructor is inserted:
// Transpiled (no class props)
class Test extends Base {
constructor() {
super(...arguments);
console.log('my special custom code');
}
}
But if I uncomment someProp and enable the class properties plugin, my custom code is overwritten:
// Transpiled (with class props)
class Test extends Base {
constructor(...args) {
super(...args);
_defineProperty(this, "someProp", 'yay');
}
}
It doesn't seem to matter what order I list the plugins. Is this expected, is there a way around it, or is this a bug?
I don't think the implementation of my plugin matters - but if it does, I can add more detail.
Any help appreciated. Thanks!
I ended up asking for help in the Babel slack community, and they were able to help me fix this issue.
The problem was that I was using a different visitor in my implementation - I had visitors specified for ClassDeclaration and ClassMethod, but the visitor in the plugin-proposal-class-properties implementation was on Class. When I changed my code to work off of Class, and made sure mine ran first, the properties were added to my custom constructor as expected.
How do I extend /include/SearchForm/SearchForm2.php in upgrade safe manner?
You could create /custom/include/SeachForm/CustomSearchForm2.php which extends SearchForm2 (the class name for SearchForm2) traditionally (e.g. CustomSearchForm2 extends SearchForm). The harder task is accessing your custom class at that point.
SearchForm is instantiated from include/MVC/View/views/view.list.php - in a couple of possible places: the protected method getSearchForm2() and [assumed] public method prepareSearchForm().
So how do you extend view.list.php? That one's easier. For any module you'd like a custom list view, create a file at /custom/modules/MyModule/views/view.list.php and define it as CustomMyModuleViewList extends ViewList. Some modules already have their own ViewList (e.g. Accounts, Calls) so for those you'd want to extend their original extended ViewList, e.g. CustomAccountsViewList extends AccountsViewList.
So create your custom ViewList extension, copy-paste the methods you need to alter (prepareSearchForm and getSearchForm2) and adjust as needed to load in your custom SearchForm class.
Assuming the question relates to SugarCRM 6.5.x (and potentially earlier 6.x versions - I haven't checked), Matthew Poer's answer is exactly right except for one thing: the class to extend is called SearchForm instead of SearchForm2. To do this:
Copy include/SearchForm/SearchForm2.php to custom/include/SearchForm/SearchForm2.php
Edit custom/include/SearchForm/SearchForm2.php and edit the class declaration, changing it to:
require_once('include/SearchForm/SearchForm2.php');
class CustomSearchForm extends SearchForm {
Copy include/MVC/View/views/view.list.php to custom/include/MVC/View/views/view.list.php
Edit custom/include/MVC/View/views/view.list.php and edit the class declaration, changing it to:
require_once('include/MVC/View/views/view.list.php');
class CustomViewList extends ViewList {
In the function prepareSearchForm in the CustomViewList class, change the line
require_once('include/SearchForm/SearchForm2.php');
to
require_once('custom/include/SearchForm/SearchForm2.php');
and the line
$searchMetaData = SearchForm::retrieveSearchDefs($this->module);
to
$searchMetaData = CustomSearchForm::retrieveSearchDefs($this->module);
In the function getSearchForm2 in the CustomViewList class, change the line
return new SearchForm($seed, $module, $action);
to
return new CustomSearchForm($seed, $module, $action);
The other functions of CustomSeachForm and CustomViewList can be subsequently overriden as needed. If you have module-specific view.list.php files, you will, of course, need to change them to extend CustomViewList instead of ViewList.
Alright so I've been continuing to learn about classes and oop languages. And am a bit confused.
If I was to have a separate class for player stats. And in that class I have some private ints and then some functions to change them publicly.
Say I want to change and get those ints From my main class. I make an object and assign them to local variables then I can call the local variables in my main script. Then update the variable in the stat class.
It seems a little silly that I have to make a local variable as well as a separate variable in a different class.
To me it would make sense to just be able to call the separate class in a new object whenever I wanted to access the variables in the stat class but I can't...
Let me know if this isn't clear as I can try to expand more.
Thanks
Ben
You do not have to make new variables in the "main" class ....
you can just use the getters and setters through the object that you created.
Also copying variables from player stats to main class is not a good idea because now you have to maintain two copies of same data, at least until you are in scope of main class. If not handled correctly it can also cause data inconsistencies.
Assuming you are using Java, you can do this.
public class PlayerStats{
private int var1=20;
public void setVar1(int var1){
this.var1=var1
}
public int getVar1(){
return var1
}
}
public class mainClass{
PlayerStats pStats = new PlayerStats();
pStats.getVar1();
pStats.setVar1(14);
System.out.println(pStats.getVar1());
}
Thanks for that answer definately cleared things up however, in the object created in mainClass if I create the object in one function how do I use it in another function in the same class?
Depends on how and if the two functions are connected and how central that object is to your class.
If the object is very central to class :
That is, you are using it almost in all the function, your class revolves around playing with that object, then you can create it at class level something along these lines
public class mainClass{
PlayerStats pStats = new PlayerStats();
public void function1() {
pStats.setVar1(14);
System.out.println(pStats.getVar1());
}
public void function2(int x) {
pStats.setVar1(x);
System.out.println(pStats.getVar1());
}
}
If two functions are not connected :
Just make a new object inside the function scope, if possible.
This is better than creating an object at class level, because the object becomes eligible for garbage collection after the function is finished executing. Whereas, the object created at class level stays in the memory as long as the object (instance of main class) is in the memory.
If two functions are connected, i.e you are calling one function from inside the second function :
you can just pass the object as an argument, something along these lines
public class mainClass{
public void function1() {
PlayerStats pStats = new PlayerStats();
pStats.setVar1(14);
function2(pStats)
}
public void function2(PlayerStats x) {
System.out.println(pStats.getVar1());
}
}
Also google dependency injection, it is an important concept, try to use it as often as possible. It produces good decoupled and testable design
There is so much more to say, people have written books on this topic, OO Design is an art in itself.
I'm using native session library to replace the built in session library in CI. I need to extend the class but when I drop in MY_Session.php, CI reverts back to the old /system/libraries/Session.php.
How to I extend a class that's replaced a core CI class like Session.php?
Simply by naming your class files identically to a native library will
cause CodeIgniter to use it instead of the native one. To use this
feature you must name the file and the class declaration exactly the
same as the native library. For example, to replace the native Email
library you'll create a file named application/libraries/Email.php
-user guide
then call it
class MY_Email extends CI_Email {
public function __construct()
{
parent::__construct();
}
}
Loading Your Sub-class:
$this->load->library('email');
EDIT
Try this:
Just load your new library (the one doing the extending):
Then, let's say we have Session.php and Mysession.php
<?php
load_class('session', false);
class Mysession extends Session {
//your code
}
You don't need the MY_ name tag still, I think you want to reserve that for it's original intended purpose to avoid confusion.
.. else just use an include() or require() :P
As mentioned in the Zend Framework manual, I created a base controller.
Subclassing the Action Controller
By design, Zend_Controller_Action must
be subclassed in order to create an
action controller. At the minimum, you
will need to define action methods
that the controller may call.
Besides creating useful functionality
for your web applications, you may
also find that you're repeating much
of the same setup or utility methods
in your various controllers; if so,
creating a common base controller
class that extends
Zend_Controller_Action could solve
such redundancy.
But it turns out, that Exceptions are not being called properly from the base... To replicate this, create a file:
/path/to/workspace/library/Joe/Controller.php
Then:
class Joe_Controller extends Zend_Controller_Action
{
public function init()
{
Throw new Zend_Exception('test', 500);
parent::init();
}
}
Then in your controller directory, IndexController.php extends off the base:
class IndexController extends Joe_Controller
{
You will find that the exception is uncaught.
If however, you don't extend off the base controller, then throw an exception in init or preDispatch, it will be caught and forwarded to the ErrorController.
Anyone have an idea on getting the exceptions caught from the Base Controller?
Thanks.
UPDATING TO TACKLE THIS ANOTHER WAY
After looking at the various articles and official documentation on how to structure the directories, I went with putting the base controller in library/Joe/...but maybe that's part of the problem...there's no guidance in the manual on how to name and place the base controller. What do the experts with a base controller do?
Another Update
Looking at my code some more, and reading on the net, seems like people suggested in should be:
abstract class Joe_Controller_Action extends Zend_Controller_Action.
Except changing it did not solve the problem...
Now considering that there are articles suggesting to use Base Controllers including the manual, would this be considered a bug in Zend Framework?
To replicate, just throw a Zend_Exception of any kind in the base init or preDispatch. Imagine you poll the database in there, (which is what I'm doing)...and the database is down. No error controller. That's not a good situation unless I'm doing something incorrectly.
My suspicion is that this is a new bug... I don't recall this problem before Zend_Application and I've been using a base controller since ZF 1.5.
Two thoughts off the top of my head:
Controller names in the default module are usually named like SomethingController. Your name Joe_Controller suggests the module Joe and an empty controller name.
In routing/dispatch, doesn't it look for a matching action before dispatch to the controller? Since the samples have no actions, might you be triggering ControllerNotFound exception?
Just throwin' out some ideas.
in Zend philosophy, they provide the init() method to avoid the hassle of
public class Module_TotoController extends Zend_Action_Controller {
public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
parent::__construct($request, $response, invokeArgs);
// some init code here
}
}
just use :
public class Module_TotoController extends Zend_Action_Controller {
public function init ()
// some init code here
}
}
Now, If you look at the Zend_Controller_Action class source, you will notice that the following methods are empty:
init()
preDispatch ()
postDispatch ()
This means, it is useless to call parent:: in your specific controller
public class Module_TotoController extends Zend_Action_Controller {
public function init ()
parent::init(); // useless ;-) but you can go for it
// some init code here
}
}
Now, if you want to put an intermediate class between Module_TotoController and Zend_Action_Controller, you expose yourself to a big hassle as:
Some controllers won't extend your "base" controller (e.g your ErrorController in your question)
so it is not a really a base of your application, is it ?
If you put some logic in your init() of that "base",
you must call the parent:: in your init(),
all the developers in the project need to be aware of that
You will ever add another little features to your "Base" controller
This will result to a big bloated file
Loading/Initializing plenty of stuff you might not really need in that lambda controller
Do you need you database on every page ?
No: doesn't a $this->_helper->connect(); look nice instead ?
Yes: use a controller plugin
This "Base" controller won't fit your other projects needs, so that class won't be reusable
Action helpers will
Controller Plugins will
Hope it makes sense
Don't go for a base or whatever controller
As documentation says :
By design, Zend_Controller_Action must be subclassed in order to create an action controller.
Agreed, this is misleading
What they meant is
class Module_TotoController extends Zend_Controller_Action {}
class Module_TotoController extends Joe_Controller is plain wrong (sorry no offence)
as you said your ErrorController can't extend your intermediate Joe_Controller class
because your exception will be thrown again in the instantiation of the ErrorController class (as excepted !!!)
The uncaught Exception error is the result of a protection to avoid loops (dig Zend\Controller\Plugin\ErrorHanlder.php line 200-ish)
If you require something to be done for every action, use a Zend_Controller_Plugin and register it with the frontController