I'm trying to wrap my head around classes in AHK. I'm C++ dev, so would like to make use of RAII (__New, __Delete), but it looks like I miss some concepts since things look very contra-intuitive for me.
After some tries I came up with this simple example:
class Scenario
{
__New()
{
MsgBox, NEW
}
__Delete()
{
MsgBox, DELETE
}
}
scenario := new Scenario
scenario := new Scenario
scenario := 1
scenario := {}
scenario := new Scenario
Return
As a result I get the following messages:
NEW
NEW
DELETE
DELETE
Questions:
Why doesn't the object get destroyed during the second assignment? I'd assume the number of refs going to 0, no?
How come I get 2 destructions in a row? Where was that object stored meanwhile? How could scenario variable hold both references?
Why was not the third construction called?
Why doesn't the object get destroyed during the second assignment?
Garbage collection had not been triggered yet
I'd assume the number of refs going to 0, no?
References going to 0 does not necessarily trigger GC
How come I get 2 destructions in a row?
Garbage collection cleaned both references at the same time
Where was that object stored meanwhile?
The heap
How could scenario variable hold both references?
scenario does not hold both references
Why was not the third construction called?
Only two Scenario objects are constructed. The variable scenario is a dynamic variable and is not always an instance of the class Scenario. The last assignment scenario := {} just creates an empty object.
Ok, found out what was missing. Two things:
AHK script is case-insensitive.
Since class is an object by itself in AHK it's possible to override the class by another object.
Here is a piece of the documentation:
Because the class is referenced via a variable, the class name cannot be used to both reference the class and create a separate variable (such as to hold an instance of the class) in the same context. For example, box := new Box would replace the class object in Box with an instance of itself. [v1.1.27+]: #Warn ClassOverwrite enables a warning to be shown at load time for each attempt to overwrite a class.
This explains what happened in the code above: variable name scenario is effectively the same as a class name Scenario, so I just quietly overrode my class with an empty object.
Also, since the new instance of the class is created before assignment, I got two 'NEW' in a row, only than 'DELETE'.
Related
So I create my class Cars. Then I make a variable(audi) for an object from my class cars. Everything is fine and dandy but I noticed that I can create an object(with an engine value of 50) without specifying a variable for it to be held in. So now how can I access that object?
#include <iostream>
using namespace std;
class Cars
{
public:
int getStatus();
Cars(int engine=5);
private:
int m_engine;
};
Cars::Cars(int engine)
{
m_engine=engine;
cout<<"A new car is made."<<endl;
}
Cars::getStatus()
{
cout<<m_engine<<endl;
}
int main()
{
Cars audi(10);
audi.getStatus();
Cars(50);
}
It depends on when you want to access the object.
Cars(50);
With this piece of code, you create a temporary object that lives only during execution of the current statement (i. e. until execution of your code passes the semicolon).
Cars(50);
// I want to access the object here
In this case: Too late. The temporary has already been destroyed and doesn't exist any more. No chance to get back to it. You can, however, use the object as long as it lives, e. g. call a member function on it or pass it to another function:
Cars(10).doSomething();
// but right now (after the semicolon), the car doesn't exist any more
doSomethingElse(Cars(12));
// again, the object got destroyed
Be aware that in above example, you created two distinct instances, each ceasing to exist when reaching the semicolon. Be aware, too, that the objects' destructors get called at this point of time.
You need to do it all together, like this:
Cars(50).getStatus();
Otherwise you won't have a way to refer to your car with 50 m_engine.
This temporary should be used with fidelity. Read more in What is an Anonymous Object?
You can't! It's already dead by the time you try. Cars(50) is a temporary, and its lifetime ends at the end of its full-expression -- that is, at the ;.
Edit: So far it looks like the answer to my question is, "You can't do that in Swift." I currently have a solution whereby the subclass names are listed in an array and I loop around and instantiate them to trigger the process I'm describing below. If this is the best that can be done, I'll switch it to a plist so that least it's externally defined. Another option would be to scan a directory and load all files found, then I would just need to make sure the compiler output for certain classes is put into that directory...
I'm looking for a way to do something that I've done in C++ a few times. Essentially, I want to build a series of concrete classes that implement a particular protocol, and I want to those classes to automatically register themselves such that I can obtain a list of all such classes. It's a classic Prototype pattern (see GoF book) with a twist.
Here's my approach in C++; perhaps you can give me some ideas for how to do this in Swift 4? (This code is grossly simplified, but it should demonstrate the technique.)
class Base {
private:
static set<Base*> allClasses;
Base(Base &); // never defined
protected:
Base() {
allClasses.put(this);
}
public:
static set<Base*> getAllClasses();
virtual Base* clone() = 0;
};
As you can see, every time a subclass is instantiated, a pointer to the object will be added to the static Base::allClasses by the base class constructor.
This means every class inherited from Base can follow a simple pattern and it will be registered in Base::allClasses. My application can then retrieve the list of registered objects and manipulate them as required (clone new ones, call getter/setter methods, etc).
class Derived: public Base {
private:
static Derived global; // force default constructor call
Derived() {
// initialize the properties...
}
Derived(Derived &d) {
// whatever is needed for cloning...
}
public:
virtual Derived* clone() {
return new Derived(this);
}
};
My main application can retrieve the list of objects and use it to create new objects of classes that it knows nothing about. The base class could have a getName() method that the application uses to populate a menu; now the menu automatically updates when new subclasses are created with no code changes anywhere else in the application. This is a very powerful pattern in terms of producing extensible, loosely coupled code...
I want to do something similar in Swift. However, it looks like Swift is similar to Java, in that it has some kind of runtime loader and the subclasses in this scheme (such as Derived) are not loaded because they're never referenced. And if they're not loaded, then the global variable never triggers the constructor call and the object isn't registered with the base class. Breakpoints in the subclass constructor shows that it's not being invoked.
Is there a way to do the above? My goal is to be able to add a new subclass and have the application automatically pick up the fact that the class exists without me having to edit a plist file or doing anything other than writing the code and building the app.
Thanks for reading this far — I'm sure this is a bit of a tricky question to comprehend (I've had difficulty in the past explaining it!).
I'm answering my own question; maybe it'll help someone else.
My goal is to auto initialize subclasses such that they can register with a central authority and allow the application to retrieve a list of all such classes. As I put in my edited question, above, there doesn't appear to be a way to do this in Swift. I have confirmed this now.
I've tried a bunch of different techniques and nothing seems to work. My goal was to be able to add a .swift file with a class in it and rebuild, and have everything automagically know about the new class. I will be doing this a little differently, though.
I now plan to put all subclasses that need to be initialized this way into a particular directory in my application bundle, then my AppDelegate (or similar class) will be responsible for invoking a method that scans the directory using the filenames as the class names, and instantiating each one, thus building the list of "registered" subclasses.
When I have this working, I'll come back and post the code here (or in a GitHub project and link to it).
Same boat. So far the solution I've found is to list classes manually, but not as an array of strings (which is error-prone). An a array of classes such as this does the job:
class AClass {
class var subclasses: [AClass.Type] {
return [BClass.self, CClass.self, DClass.self]
}
}
As a bonus, this approach allows me to handle trees of classes, simply by overriding subclasses in each subclass.
I'm building a Dart app which contains a variety of class objects. The particular class object I'm dealing with contains a variety of stream event listeners on DOM elements. When I remove these objects from the DOM and untrack the class object these listeners persist.
I know that Dart runs garbage collection eventually, but I'm not even 100% sure it will come along and delete these class objects since there is a Watcher and Stream listeners that continue.
My question is, is there a way to actively delete a class object immediately? I tried setting the class object to null but that doesn't seem to work for some reason. When I check if the object exists afterward with a print statement, it still lists it as an instance of that class object.
Furthermore, for what I'm trying to accomplish, canceling streams doesn't seem to be enough. I need to destroy the class object.
Setting references to null is all you can do. Your test seems very weird. How can you print the object if you don't have a reference? If you still have a reference, how can you expect the instance to be collected.
Hi I have a situation where I need to look up the number of recently viewed products on catalog/product/view.phtml. In the recently viewed 'product_viewed.phtml' file it calls
$_products = $this->getRecentlyViewedProducts()
to get the recently viewed. How would I access this method from within the catalog/product/view.phtml file?
I don't know where this method is. I've tried searching for it but it doesn't seem to exist. When I write click it in Netbeans and click go to declaration it takes me to
class Mage_Reports_Block_Product_Viewed extends Mage_Reports_Block_Product_Abstract
Actually on the class itself. This class only has _toHtml(), getCount(), and getPageSize() methods.
I just need to know whether there are any recently viewed products.
Any help most appreciated!
Billy
If you look into 'Mage_Reports_Block_Product_Viewed', you will notice:
$this->setRecentlyViewedProducts($this->getItemsCollection());
That 'getItemsCollection' method is defined in the abstract class... And you will notice this abstract class will create a model based on $_indexName defined in the (subclassed) block.
If you just want the collection, you can probably get away with:
$_products = Mage::getModel('reports/product_index_viewed')->getCollection();
And then adding whatever you want to the collection:
$_products
->addAttributeToSelect('*')
->setAddedAtOrder();
// optionally add other methods similar to Mage_Reports_Block_Product_Abstract::getItemsCollection
Another approach that might be more suited would be to create the original block:
$productViewedBlock = $this->getLayout()->createBlock('reports/product_viewed');
On which you can simply call whatever you want:
$_collection = $productViewedBlock->getItemsCollection();
$_count = $productViewedBlock->getCount();
The getRecentlyViewedProducts function is a magical getter that gets the data that was set with setRecentlyViewedProducts in app/code/core/Mage/Reports/Block/Product/Viewed.php (which builds it using app/code/core/Mage/Reports/Block/Product/Abstract.php's function _getRecentProductsCollection).
This is complicated stuff that you don't want to reproduce; its better, IMO to make your own Block that extends Mage_Catalog_Block_Product_Abstract that will give you access to the same functionality, and drop your new block into the page you're working on.
I'm building a MEF-based plugin-centric WPF application and I'm facing an issue with GetExports, maybe it's just my ignorance but I find an odd behaviour. I have a number of exported parts, all derived from 2 different interfaces (let's name them A and B), but all marked with the same metadata attribute X. So I have code like:
[Export(typeof(A))]
[TheXAttributeHere...]
public class SomePart1 : A { ... }
for each part, and the same for classes implementing B:
[Export(typeof(B))]
[TheXAttributeHere...]
public class SomePart2 : B { ... }
Now, when I try getting all the parts implementing A and decorated by attribute X with some values, MEF returns not only the A-implementing parts, but ALSO the B-implementing parts. So, when I expect to deal with A-objects I get a B, whence a cast exception.
In the real world, interfaces are named IItemPartEditorViewModel and IItemPartEditorView, while their common attribute is named ItemPartEditorAttribute and exposes a PartType string property on which I do some filtering. My code to get parts is thus like e.g.:
var p = (from l in container.GetExports<IItemPartEditorViewModel, IItemPartEditorMetadata>()
where l.Metadata.PartType == sPartType
select l).FirstOrDefault();
When looking for IItemPartEditorViewModel whose PartType is equal to some value, I get the IItemPartEditorView instead of IItemPartEditorViewModel implementing object. If I comment out the attribute in the IItemPartEditorView object instead, I correctly get the IItemPartEditorViewModel implementing object.
Update the suggested "templated" method was used, but I mistyped it here as I forgot to change lessthan and greaterthan into entities. Anyway, reviewing the code I noticed that in the attribute I had "ViewModel" instead or "View" for the interface type, so this was the problem. Shame on me, sorry for bothering :)!
I think I'd need to see more of the code to know for sure what's going on. However, I'd suggest you call GetExports like this:
// Get exports of type A
container.GetExports<A>();
// Get exports of type B
container.GetExports<B>();
Then do your filtering on the list returned. This will probably fix the cast issues you are having. I'd also be interested in seeing the code for the custom metadata attribute. If it derives from ExportAttribute for example, that might be part of the problem.