6

I don't know if Apex supports generics but how can I make the below class more generics where I should be able to pass any data type?

below is the example:

the problem I have is this:

public class Criteria {
   public String FieldName; 
   public String Operator;      
   public String FieldValue;
   public Criteria(String f_name, String f_value) {
       FieldName = f_name;
       FieldValue = f_value;
       Operator = '=';
   }
   public String getSOQLCriteria() {
       return fieldName + ' '  + Operator + ' \'' + FieldValue + '\'';
   }    
   public String IsFieldValueGiven() {
       return FieldValue != null && FieldValue != '';
   }
}

calling the code:

Criteria c1 = new Criteria('empNum__c', 'john'); //good

the issue is, if I have number or date then below code will not work, its expecting string, what do I need to do to make it work the above class code more in a generic way?

Criteria c2 = new Criteria('empNum__c', 145); //number - error

3 Answers 3

6

You want to use Object as a generic class to use. Also, no need to check null AND an empty string (it'll always be null or a non-empty string). Here's the modifications you want:

public class Criteria {
   public String FieldName; 
   public String Operator;      
   public Object FieldValue;
   public Criteria(String f_name, Object f_value) {
       FieldName = f_name;
       FieldValue = f_value;
       Operator = '=';
   }
   public String getSOQLCriteria() {
       if(FieldValue instanceOf String) {
           return FieldName + Operator + String.escapeSingleQuotes(String.valueOf(FieldValue));
       }
       return FieldName + Operator + FieldValue;
   }
   public String IsFieldValueGiven() {
       return FieldValue != null;
   }
}

The actual getSOQLCriteria method would need to check the data type of the field value to determine the appropriate method to use. The above method should work for all primitive data types.

6
  • Interesting. It looks like the + operator for string concatenation can handle Object type arguments and somehow manages to convert them to strings.
    – martin
    Commented Jul 21, 2017 at 2:10
  • one question how will this getSOQLCriteria method will take care if the f_value is integer, its enclosing a single quote
    – Nick
    Commented Jul 21, 2017 at 14:01
  • @NickKahn Yeah, I should have modified that. I went ahead and edited in a version that should work for most purposes.
    – sfdcfox
    Commented Jul 21, 2017 at 14:08
  • One thing I found is that if I'm passing Date it treating as String and hence its adding the singleQuotes, and I try to add one more if(FieldValue instanceOf Date) { return FieldName + Operator + FieldValue; } but its not exuecting that if condition, any idea?
    – Nick
    Commented Jul 21, 2017 at 17:15
  • @NickKahn If you're binding to a String, it'll be a string. Your controller itself should be converting the value to the appropriate type with Decimal.valueOf, Date.valueOf, etc. This is only one part of the solution for what you're attempting to do.
    – sfdcfox
    Commented Jul 21, 2017 at 17:43
4

In Apex, the best you can do is change the parameter on your constructor to have the generic Object type.

If you need to process the values in a particular way based on type, you can use the instanceof keyword to determine what type of data got passed in, but in general though, the String.valueOf() method is a good catch-all.

class

  1 public class MyClass{
  2 
  3     String s;
  4 
  5     public MyClass(Object o){
  6        s = String.valueOf(o);
  7     }
  8 }

anonymous block

  2 system.debug(new MyClass('53'));
  3 system.debug(new MyClass(53));
  4 system.debug(new MyClass(53.3));
  5 system.debug(new MyClass(System.today()));
  6 system.debug(new MyClass(new Account(Name='My Account')));

debug log

09:37:20.86 (92471396)|USER_DEBUG|[2]|DEBUG|MyClass:[s=53]
09:37:20.86 (92535244)|USER_DEBUG|[3]|DEBUG|MyClass:[s=53]
09:37:20.86 (92598190)|USER_DEBUG|[4]|DEBUG|MyClass:[s=53.3]
09:37:20.86 (92651329)|USER_DEBUG|[5]|DEBUG|MyClass:[s=2017-07-21 00:00:00]
09:37:20.86 (92858629)|USER_DEBUG|[6]|DEBUG|MyClass:[s=Account:{Name=My Account}]

From the Apex documentation on String methods:

public static String valueOf(Object toConvert)

If the argument is not a String, the valueOf method converts it into a String by calling the toString method on the argument, if available, or any overridden toString method if the argument is a user-defined type. Otherwise, if no toString method is available, it returns a String representation of the argument.

I haven't been able to track down how exactly this method "returns a String representation of the argument" when there is no toString() method available, but despite the lack of visibility into the internals, this method is very handy.

5
  • error: Method does not exist or incorrect signature: [Object].toString()
    – Nick
    Commented Jul 21, 2017 at 0:58
  • That's what I meant by the comment "handle other possibilities"
    – martin
    Commented Jul 21, 2017 at 0:59
  • I'm not sure understand what you mean by handle other possibilities, can you show me number and date example in your answer?
    – Nick
    Commented Jul 21, 2017 at 1:01
  • 1
    You got that "method does not exist" error because you tried to call toString method from Object, which doesn't exist. As Nick said, you should instead convert the object to a string using String.valueOf(obj). Commented Jul 21, 2017 at 2:11
  • @RenatoOliveira I said that, but yes, that is correct.
    – martin
    Commented Jul 21, 2017 at 2:12
0

You created the method with arguments of String type and you are passing Integer.

To achieve this, you should send the number also in quotes and should use type casting.

Integer.valueof()

or create multiple methods with same name and different parameter type! - Method overloading.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .