Can somebody tell me why the autocompletion doesn't work when I'm using a getInstance() method instead of new ClassName?
Following is the getInstance() method of the class:
// Define The Namespace For Our Library
namespace JUnstoppable;
class JUnstoppable
{
// Instance Of The Class
protected static $instance = array ();
public static function getInstance ($forPlatformName = 'joomla')
{
$forPlatformName = strtolower($forPlatformName);
if (!isset(static::$instance[$forPlatformName]))
{
static::$instance[$forPlatformName] = new \JUnstoppable\JUnstoppable($forPlatformName);
}
return static::$instance[$forPlatformName];
}
public function __construct ($platformName = 'joomla')
{
}
public function doExecute ($test = 'lalala')
{
return $test;
}
}
Can somebody tell me why the autocompletion doesn't work when I'm using a getInstance() method instead of new ClassName?
That's because IDE does not know what can be inside your $instance static property and therefore it cannot figure out what getInstance() returns. From IDE point of view it's just plain array (elements of any types) and not an array of JUnstoppable instances.
You can place caret on $test and invoke View | Quick Documentation to see what IDE knows about that variable. If it does not say JUnstoppable there then no wonders.
Just add proper type hint for return value of getInstance() method via PHPDoc's #return tag:
/**
* My super method.
*
* #param string $forPlatformName Optional parameter description
* #return JUnstoppable
*/
public static function getInstance ($forPlatformName = 'joomla')
You can specify concrete class (JUnstoppable in this case) .. or static if this method will be used by child classes as well and they will return different instances.
Alternatively (or better say: in addition) you can typehint $instance property which IDE will use to figure out what getInstance() method returns:
/** #var JUnstoppable[] Instance Of The Class */
protected static $instance = array ();
Related
I've created a new XmlResponseFormatter and now I want to change the rootTag.
class newXmlResponseFormatter extends XmlResponseFormatter
{
/**
* #var string the name of the root element.
*
*/
public $rootTag;
public function __construct($rootTag) {
parent::__construct();
$this->rootTag = $rootTag;
}
}
From a controller I set that value:
$xmlFormater = new newXmlResponseFormatter('newRootTag');
In the controller that value is available, and it sets in $rootTag but it threw the following exception:
exception 'yii\base\InvalidConfigException' with message 'Missing required parameter "rootTag" when instantiating "app\components\override\newXmlResponseFormatter".' in /var/www/html/Admin/vendor/yiisoft/yii2/di/Container.php:451
Does anyone know what can be a problem?
Thanks in advance!
First parameter in XmlResponseFormatter is $config, because XmlResponseFormatter extends Object class. You are violated liskov substitution principle.
You should rewrite your constructor like this:
class newXmlResponseFormatter extends XmlResponseFormatter
{
/**
* #var string the name of the root element.
*
*/
public $rootTag;
/**
* newXmlResponseFormatter constructor.
*
* #param string $rootTag
* #param array $config
*/
public function __construct($rootTag, $config = [])
{
$this->rootTag = $rootTag;
parent::__construct($config);
}
}
In yii2 you should call parent constructor after your code, and call parent init before your code.
$config need for simple configure model like this:
new newXmlResponseFormatter(['rootTag' => 'newRootTag']);
I wanna pass class reference when dispatching the deluxe signals in AS3Signals ?
My code here for dispatch,
public var signal:DeluxeSignal = new DeluxeSignal(this);
protected function button1_clickHandler(event:MouseEvent):void
{
signal.dispatch(new GenericEvent());
}
and here i listen,
protected function creComp(event:FlexEvent):void
{
viewB.signal.add(onDeluxDispatched);
}
private function onDeluxDispatched(e:GenericEvent):void
{
trace(e.target, e.signal);
trace(e.currentTarget);
trace("SignalTest.onDeluxDispatched(e)");
}
But i received null in trace.
where i am wrong ?
from the documentation of DeluxeSignal class ( https://github.com/robertpenner/as3-signals/blob/master/src/org/osflash/signals/DeluxeSignal.as )
/**
* Creates a DeluxeSignal instance to dispatch events on behalf of a target object.
* #param target The object the signal is dispatching events on behalf of.
* #param valueClasses Any number of class references that enable type checks in dispatch().
* For example, new DeluxeSignal(this, String, uint)
* would allow: signal.dispatch("the Answer", 42)
* but not: signal.dispatch(true, 42.5)
* nor: signal.dispatch()
*
* NOTE: Subclasses cannot call super.apply(null, valueClasses),
* but this constructor has logic to support super(valueClasses).
*/
public function DeluxeSignal(target:Object = null, ...valueClasses)
it has to be declared and dispatched that way :
public class ClassName {
public var signal:DeluxeSignal = new DeluxeSignal(this, ClassName);
private function dispatch():void {
signal.dispatch(this);
}
}
then retrieved that way in the referenced class :
public class Parent {
private var childClass:ClassName;
private function bindSignal() {
childClass.signal.add(signalListener);
}
private function signalListener(classReference:ClassName) {
/* do your stuff with classReference */
}
}
i ran into same issue and that worked for me
Depending on your requirements you may not need to use DeluxeSignal. I'll use Willo's example to illustrate.
public class Parent {
private var childClass:ClassName;
private function bindSignal() {
childClass.signal.add(signalListener);
}
private function signalListener(classReference:ClassName) {
/* do your stuff with classReference */
}
}
Yes, we get a class reference. But this class reference is not the one that was passed to DeluxeSignal when it was instantiated, but instead it is the one that was passed to dispatch.
public class ClassName {
/* this is not the reference to 'this' that the listener gets. in fact,
all this one does is sit inside the signal as a property */
public var signal:DeluxeSignal = new DeluxeSignal(this, ClassName);
private function dispatch():void {
signal.dispatch(this); // this is the reference that the listener gets
}
}
The reference we passed into the constructor just sits inside a public property called target.
public function DeluxeSignal(target:Object = null, ... valueClasses) {
/* the reference is set as _target and is not used anywhere else in the
class other than in the setter/getter */
_target = target;
valueClasses = (valueClasses.length == 1 && valueClasses[0] is Array) ? valueClasses[0] : valueClasses;
super(valueClasses);
}
public function get target():Object { return _target; }
public function set target(value:Object):void {
if (value == _target) return;
removeAll();
_target = value;
}
So it seems the idea is to access this property when the listener is called, using a reference to the signal:
public class Parent {
private var childClass:ClassName;
private function bindSignal() {
childClass.signal.add(signalListener);
}
private function signalListener() {
/* not passing the reference in the dispatch() call means we can
still access the target at this point by using... */
childClass.signal.target;
/* but it just feels nicer to have the reference provided as an
argument rather than as a mutable property, right? */
}
}
Technically that works but it doesn't feel great to be getting a reference from what is a mutable property.
Where it might come in handy though is when using a dependency injection framework like Robotlegs, where the signal is injected into a command. Your command wouldn't have a listener with which to be provided a reference in an argument, but it would be able to access the reference from the signal via its target property.
The way Willo used DeluxeSignal here though, you can actually use the plain old Signal class to do exactly the same thing with less overhead.
public class ClassName {
/* note: no pointless use of 'this' in the constructor. instead,
just the types we will actually be providing to the listener */
public var signal:Signal = new Signal(ClassName, String);
private function dispatch():void {
signal.dispatch(this, "Whatever else you want");
}
}
And on the other end you get this.
public class Parent {
private var childClass:ClassName;
private function bindSignal() {
childClass.signal.add(signalListener);
}
private function signalListener(classReference:ClassName, foo:String) {
/* do your stuff with classReference */
}
}
So you get the same result for typing less code and for less inheritance overhead.
Where you might want to use DeluxeSignal though, other than when needing to keep a reference to the target in your DI frameworks, is when you're using native events. DeluxeSignal overrides the dispatch method to do some extra work with those.
I have written this method in a parent class in order to be able to get instances of children too.
/** #return static */
public static function getInstance()
{
/** #var $instance static */
static $instance = false;
if (!$instance) {
$instance = new static();
}
return $instance;
}
When I get the instance, PhpStorm doesn't know about child class implementation (methods, constants, etc). How can I tell him about them?
In snippet I am suggesting #return and #var as methods that work in contexts that don't imply static refference.
#return static does work in PhpStorm 6 (I tested in 6.0.2.) So you should upgrade to the latest version if you want to use this feature.
I want to pass Value from Constructor in my Main Class to another Class.
Main Class:
public function Main() {
Snap.locationX = 350;
}
Another Class:
public function get locationX():Number{
return _value;
}
public function set locationX(x:Number):void{
_value = x;
}
It returns 1061: Call to a possibly undefined method locationX through a reference with static type Class.
What am I doing wrong?
The setter and getter methods you have defined above are INSTANCE methods. It seems like you are calling Snap.locationX on the Snap class itself and not on an instance of the Snap class.
try (under Main()):
var snapObj:Snap = new Snap();
snapObj.locationX = ...
I'm learning AS3, and am a bit confused as to what a static variable or method does, or how it differs from a method or variable without this keyword. This should be simple enough to answer, I think.
static specifies that a variable, constant or method belongs to the class instead of the instances of the class. static variable, function or constant can be accessed without creating an instance of the class i.e SomeClass.staticVar. They are not inherited by any subclass and only classes (no interfaces) can have static members. A static function can not access any non-static members (variables, constants or functions) of the class and you can not use this or super inside a static function. Here is a simple example.
public class SomeClass
{
private var s:String;
public static constant i:Number;
public static var j:Number = 10;
public static function getJ():Number
{
return SomeClass.j;
}
public static function getSomeString():String
{
return "someString";
}
}
In the TestStatic, static variables and functions can be accessed without creating an instance of SomeClass.
public class TestStaic
{
public function TestStaic():void
{
trace(SomeClass.j); // prints 10
trace(SomeClass.getSomeString()); //prints "someString"
SomeClass.j++;
trace(SomeClass.j); //prints 11
}
}
A static variable or method is shared by all instances of a class. That's a pretty decent definition, but may not actually make it as clear as an example...
So in a class Foo maybe you'd want to have a static variable fooCounter to keep track of how many Foo's have been instantiated. (We'll just ignore thread safety for now).
public class Foo {
private static var fooCounter:int = 0;
public function Foo() {
super();
fooCounter++;
}
public static function howManyFoos():int {
return fooCounter;
}
}
So each time that you make a new Foo() in the above example, the counter gets incremented. So at any time if we want to know how many Foo's there are, we don't ask an instance for the value of the counter, we ask the Foo class since that information is "static" and applies to the entireFoo class.
var one:Foo = new Foo();
var two:Foo = new Foo();
trace("we have this many Foos: " + Foo.howManyFoos()); // should return 2
Another thing is static functions could only access static variables, and couldn't be override, see "hidden".