Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Given 3 variables:

String a = 'Apple';
String b = 'Orange';
String varname = 'a';

Is there a way that I can use varname as a link to the variable a in my code such that the following would evaluate to true?:

if (Var(varname)=='Apple')

I know that there are ways to do it in some scripting languages such as PHP but have been unable to find any mention of this in Apex searching the web.

The PHP equivalent of what I'm after appears to be $($varname).

share|improve this question
    
There's nothing out of the box, but there is a solution that should approach what you're looking for. –  sfdcfox Jan 17 at 16:48
add comment

4 Answers

up vote 12 down vote accepted

No. Apex is a compiled language, what you're describing are variable variables typically found in languages that are parsed (interpreted) at runtime (let's not dig into opcodes, Zend's virtual machine, Facebook's HipHop etc).

Apex can be pretty flexible when executing queries from strings (but compiled query performs faster) and there are ways to do something like SELECT * FROM Account and access all fields on the object.

Search the documentation for "dynamic Apex" but the bottom line is that the code has to be compiled before it's executed. Maybe if you'd write more about your requirements (like accessing all name-value parts in URL?) we'd be able to assist more.

You can also try to use the API to fire off ExecuteAnonymous calls (code snippets that are run and discarded, they won't be saved as new class for example) but that's getting bit hardcore...

There's Type class that lets you instantiate variables in dynamic way - but you still have to specify the variable name at compile-time. There's instanceof operator, interfaces, How to invoke a method of an apex class at run time... lots of options to "do it right".


Edit: I forgot about 1 more hack: JSON.deserialize* methods. They come in few flavours... But even then you have to dump them into "some named variable" and (in the example without expected type definition) access as the Map example from other answers. So at best you'd be getting a map with many interesting properties. If you're interested in bit more complex example of casting - check out http://stackoverflow.com/questions/3122038/how-do-i-integrate-salesforce-with-google-maps, I'm pretty happy how that one turned out.

share|improve this answer
    
nice comprehensive brainstorm covering all avenues –  user320 Jan 17 at 13:26
3  
@user320 reminds me the glorious days of #define true false /* Happy debugging suckers */ ;) –  eyescream Jan 17 at 13:59
1  
Thank you @eyescream this was very informative. –  Venko Jan 17 at 16:16
    
You forgot about object maps... –  sfdcfox Jan 17 at 16:47
add comment

I do not believe this is directly possible, however using a map of the variables to a String you would be able to check for a specific variable name and produce the effect shown in your example.

Map<String,String> varNameToValueMap = new Map<String,String>();
varNameToValueMap.put('a','Apple');
varNameToValueMap.put('b','Orange');

String varname = 'a';

Then you could execute the if statement shown in your question as follows.

if(varNameToValueMap.get(varname) == 'Apple')
share|improve this answer
add comment

You can do this with a Map type. It's the Apex equivalent of a PHP associative array.

String varname = 'a';

Map<String,String> vars = new Map<String,String>{
    'a' => 'Apple',
    'b' => 'Orange',
};

if (vars.get(varname) == 'Apple') {
    //
}
share|improve this answer
    
The PHP equivalent of what I'm after appears to be $($varname). –  Venko Jan 17 at 12:20
1  
Variable variables are bad enough practise in PHP and not supported in Apex @Venko –  user320 Jan 17 at 12:25
add comment

Dynamic variables do not exist in Apex Code, because it is a "strongly typed" language. Languages such as PHP are "loosely typed" languages, which means that they are partly compiled, and then interpreted as a scripting language.

However, if you truly wanted to emulate dynamic variables, you could use the following class:

global class Vars {
    static map<object, map<object, object>> values = new map<object, map<object, object>>();
    global static object get(object scope, object key) {
        if(!values.containskey(scope)) {
            return null;
        }
        return values.get(scope).get(key);
    }
    global static void set(object scope, object key, object value) {
        if(!values.containskey(scope)) {
            values.put(scope, new map<object, object>());
        }
        values.get(scope).put(key, value);
    }
    global static boolean isset(object scope, object key) {
        return values.containskey(scope) && values.get(scope).containsKey(key);
    }
    global static void remove(object scope, object key) {
        if(isset(scope, key)) {
            values.get(scope).remove(key);
        }
        if(values.get(scope) != null && values.get(scope).isEmpty()) {
            values.remove(scope);
        }
    }
    global static void remove(object scope) {
        values.remove(scope);
    }
    global static boolean isempty(object scope, object key) {
        return !isset(scope, key) || values.get(scope).get(key) == null || String.valueOf(values.get(scope).get(key)) == '';
    }
    global static boolean isequal(object scope, object key, object value) {
        return !isempty(scope, key) && get(scope, key).equals(value);
    }
}

Usage

// Set a global variable
vars.set(null, "myvar", 12345);
// Set a local variable
vars.set(this, "myvar", 12345);
// Get a global variable; must cast to get to a primitive type
integer a12345 = (integer)vars.get(null, "myvar");
// Get a local variable; must cast to get to a primitive type
integer a12345 = (integer)vars.get(this, "myvar");
// See if a value is as expected
if(vars.isequal(this, "myvar", 12345)) { ... }
// See if a value has been set
if(vars.isset(this, "myvar")) { ... }
// See if a value is blank or not
if(vars.isempty(this, "myvar")) { ... }
// Store a complex object
vars.set(null, "myvar", new map<string, account>());
// Access a complex object; cast is required
((map<string, account>)vars.get(null, "myvar")).put("some account", new Account());
// remove a variable from a scope
vars.remove(null, "myvar");
// remove all variables in a scope
vars.remove(this);

As you can see, there are some subtleties involved to make this work, such as requiring casts to concrete types, but this system is fuctionally similiar to dynamic variables. Note that casting is required for most operations, such as accessing a specific method or using any comparison operator other than ==, !=, ===, or !== (such as <, >, etc). Also, you can't store references to functions, because the language doesn't allow that, and you can't access a function without casting. For example, the following code won't work: vars.get(null, "myvar").put("some account", new account());.

Feel free to experiment with this code and see what you can do. In the end, it may be more trouble than it's worth (I think so), but this should give you some idea of the potential capabilities of the language. Even though dynamic variables aren't directly supported, you can achieve some degree of freedom. Also note that, unlike a regular dynamic variable situation, you can use any value as a key, including dates, numbers, complex objects, etc.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.