In JavaScript, and other Object oriented languages, you can instantiate a new instance of a class, and use a method of the class instance in the same line. For example:
class customClass {
method(){
return "hello"
}
}
var s = (new customClass).method() // s = "hello"
If I try the same in VBA:
s = (new customClass).method()
I get a Compile error: Expected: end of statement, while highlighting the . after customClass).
If you like you can do the following:
Dim c as new customClass: s=c.method()
however in this case, in my opinion, it is not clear that s is being set at all making code more difficult to manage.
Is there an alternative method which makes the line clearer to understand, while still being quick and easy to write?
Sure you can.
With New Collection: .Add 42: Debug.Print .Count: End With
I'd probably want to chew the head off whoever put that in production code, but sure you can.
Doesn't mean you should.
Note that for some reason you don't get IntelliSense for With block variable references in such inline With blocks.
May or may not have something to do with VBA code shouldn't be written like this.
If the method you want to invoke doesn't alter global or instance state, consider specifying a VB_PredeclaredId module attribute on your class instead (export the module, edit its header in Notepad, re-import the module).
That way this code becomes legal, and looks much more VBA-idiomatic:
SomeCustomClass.SomeMethod
The mechanics are identical to those involved when people do UserForm1.Show off the default instance, without creating a New object.
You can pass a new instance of a class to the CallByName Function and have it access the method for you.
Dim s As String: s = CallByName(New customClass, "method", VbMethod)
Currently I have thought of 2 methods of solving the problem.
The first method I came up with is a bit hacky, but it does the trick:
s = Array(new someClass)(0).method()
However in general this method is quite confusing and difficult to read... So instead I figured you could just use a helper function instead:
function proxy(a as variant) as variant
if isObject(a) then
set proxy = a
else
proxy = a
end if
end function
sub textProxy()
s = proxy(new someClass).method()
debug.print s
end sub
It is a shame however that you lose the intelisense in both of these examples... But I guess that's more of a problem with the VBE than the methods themselves.
Related
The behaviour can be observed by placing this code in a playground:
import Foundation
import ObjectiveC
class TestClass {}
var obj = TestClass()
let stringValue = "xyz"
let key = "def"
objc_setAssociatedObject(obj, key, stringValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
//let f = "f"
let returnedString = objc_getAssociatedObject(obj, key)
This works and returns "xyz" from the objc_getAssociatedObject call.
However, if you remove the comment from the let f = "f" line. The objc_getAssociatedObject call now returns nil.
I'm baffled as to how setting a totally unrelated variable can effect the call.
Any ideas?
Looks like a bug.
The objc_... methods are part of the Objective-C runtime. They shouldn't exist in Swift.
That said they clearly do. So my guess is that there's something happening when you set that method that kicks the runtime, similar to calling synchronize on NSUserDefaults.
Edit: This NSHipster article explains that the ObjC runtime is actually there.
Edit 2: I tried a few experiments, and I'll make your question even weirder. Wrapping the test case inside the object yields the same result. But changing the variable name to an underscore fixes the problem:
let _ = "f"
I bet assigning a variable overwrites whatever runtime associations you set manually. The underscore just tells the compiler that you aren't using the result of the assignment.
I have a MATLAB class that contains a method that employs a persistent variable. When certain conditions are met I need to clear the persistent variable without clearing the object to which the method belongs. I've been able to do this, but only by employing clear functions which has excessively broad scope for my purposes.
The classdef .m file for this problem:
classdef testMe
properties
keepMe
end
methods
function obj = hasPersistent(obj)
persistent foo
if isempty(foo)
foo = 1;
disp(['set foo: ' num2str(foo)]);
return
end
foo = foo + 1;
disp(['increment foo: ' num2str(foo)]);
end
function obj = resetFoo(obj)
%%%%%%%%%%%%%%%%%%%%%%%%%
% this is unacceptably broad
clear functions
%%%%%%%%%%%%%%%%%%%%%%%%%
obj = obj.hasPersistent;
end
end
end
A script that employs this class:
test = testMe();
test.keepMe = 'Don''t clear me bro';
test = test.hasPersistent;
test = test.hasPersistent;
test = test.hasPersistent;
%% Need to clear the persistent variable foo without clearing test.keepMe
test = test.resetFoo;
%%
test = test.hasPersistent;
test
The output from this is:
>> testFooClear
set foo: 1
increment foo: 2
increment foo: 3
increment foo: 4
set foo: 1
test =
testMe
Properties:
keepMe: 'Don't clear me bro'
Methods
which is the desired output. The problem is that the line clear functions in the classdef file clears all functions in memory. I need a way to clear with a much smaller scope. For example, if hasPersistent' was a function instead of a method, the appropriately scoped clear statement would beclear hasPersistent`.
I know that clear obj.hasPersistent and clear testMe.hasPersistent both fail to clear the persistent variable. clear obj is similarly a bad idea.
Following the discussion in the comments, I think you want to use make foo a private property, accompanied with appropriate increment/reset public functions.
You definitely don't need a persistent variable to implement what you want. But, in any case, to remove a persistent variable from a class method you have to clear the corresponding class. In your case, clear testMe should do what you want.
A related issue is how to clear a persistent variable in a package function. To remove persistent variable myVar from function foo within package foo_pkg you have to do this:
clear +foo_pkg/foo
This should work as long as the parent folder of folder +foo_pkg is in the MATLAB path.
I have coded the following, and am very new to c++, and it feels clumsy. I am trying to give 'spriteBatch' (a unique_Ptr) class scope. Here's the header file:
ref class CubeRenderer : public Direct3DBase
{
public:
CubeRenderer();
~CubeRenderer();
private:
std::unique_ptr<SpriteBatch> spriteBatch;
};
Then in the cpp file Constructor, this:
std::unique_ptr<SpriteBatch> sb(new SpriteBatch(m_d3dContext.Get()));
spriteBatch = std::move(sb);
It just seems clumsy the way I had to create 'sb' and move it to 'spriteBatch'. attempting to assign directly to 'spriteBatch' failed (maybe I simply don't know the proper syntax). Is there a way to avoid needing to use 'sb' & std::move?
Thank you.
The following should work fine:
spriteBatch = std::unique_ptr<SpriteBatch>(new SpriteBatch(m_d3dContext.Get()));
Alternatively, you can avoid repeating the type name with some make_unique function.
spriteBatch = make_unique<SpriteBatch>(m_d3dContext.Get());
There's also the reset member:
spriteBatch.reset(new SpriteBatch(m_d3dContext.Get()));
But, since you mention a constructor, why not just use the member initialization list?
CubeRenderer::CubeRenderer()
: spriteBatch(new SpriteBatch(m_d3dContext.Get())) {}
I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.
So if I create an object test, and it has a property color. When I add this object to an array list I typically can access this using myarray(0).color but intellisense doesn't 'know' that I have a 'test' object inside the array. It would let me type myarray(0).whatever but would then crash if I made typo. It seems like I should be able to let it know what type of object I am trying to work with inside the arraylist.
In code maybe something like this
dim testobject as new test
testobject.color = "red"
dim testarray as new arraylist
testarray.add(testobject)
testarray(0).color = "blue"
Could someone tell me the name of this concept, and a more correct(if there is one) of how I should be doing this?
Thanks for any thoughts!
use generics instead
dim a as System.collections.generic.List(of test)
a(0).asf ' Errror