When to cast a variable - oop

Casting in Apex seems like Black Magic to me. I don't get when should we make an explicit cast, and when it can be implicit. Like:
Recipe.apxc
public virtual class Recipe{
public string nome;
protected string instructions;
private String source = 'Granny';
public Recipe() {}
public Recipe(String inpNome, String inpInstrucoes) {
nome = inpNome;
instructions = inpInstrucoes;
}
public void printDescription(){
system.debug('Name: ' + nome + ', Instructions: ' + instructions);
return;
}
}
DrinkRecipe.apxc
public class DrinkRecipe extends Recipe{
public String nome = 'Luso';
private String glassType;
public DrinkRecipe(String inpNome, String inpInstrucoes){
super(inpNome, inpInstrucoes);
}
}
in the annonymous window
DrinkRecipe dr = new DrinkRecipe('Whater', 'glu, glu', 'normal');
// why does this work? Shouldn't i always need to cast an object to make it use another constructor, from another class?
Recipe r1 = dr;
system.debug(r1.nome);
// I thought explicit casting like this would be the only way
Recipe r2 = (Recipe) dr;
system.debug(r2.nome);
Thanks

In general, Apex requires you to explicitly convert one data type to another. For example, a variable of the Integer data type cannot be implicitly converted to a String. You must use the string.format method. However, a few data types can be implicitly converted, without using a method.
Numbers form a hierarchy of types. Variables of lower numeric types can always be assigned to higher types without explicit conversion. The following is the hierarchy for numbers, from lowest to highest:
Integer
Long
Double
Decimal
Note
Once a value has been passed from a number of a lower type to a number of a higher type, the value is converted to the higher type of number.
In addition to numbers, other data types can be implicitly converted. The following rules apply:
IDs can always be assigned to Strings.
Strings can be assigned to IDs. However, at runtime, the value is checked to ensure that it is a legitimate ID. If it is not, a runtime exception is thrown.
The instanceOf keyword can always be used to test whether a string is an ID.

Related

How to construct single character constants

How do I define a constant Char value, similar to vbCr? This does not work...
Public Const ctrM As Char = "\m"C
This says the constant must have exactly one character. Well, ok, isn't that what "\m" is?, what about the following
Public Const ctrM as Char = Convert.ToChar(9)
That's not allowed because it's a function. Huh. Luckily this does work:
Public Dim ctrM as Char = Convert.ToChar(9)
But this seems sub-optimal. Am I missing something here?
The answer by fsintegral is fine, but can be slightly simpler. And you can use the Framework functions if you prefer them to the VB Functions.
Class method:
Public Class AppConsts
Public Shared ReadOnly CtrlEM As Char = Convert.ToChar(25)
Public Shared ReadOnly CtrlT As Char = Convert.ToChar(9)
Public Shared ReadOnly CtrlN As Char = Convert.ToChar(10)
Public Shared ReadOnly CtrlM As Char = Convert.ToChar(13)
Public Shared ReadOnly CrLf As String = CtrlN & CtrlM
...
End Class
'Usage:
Dim s as string = "..." & AppConts.CtrlEM
They will even show up in intellisense. If you dont like the Type/Class name intruding, you can import the class (I kind of like the Type portion included because it narrows the IntelliSense list rapidly to the relevant values):
Imports AppConsts
....
Dim s As String = CtrlEM
Alternatively, you can use the module method:
Module Program
Friend ReadOnly CtrlM As Char = Convert.ToChar(25)
End Module
' usage:
Dim s2 As String = "xxxx..." & CtrlM
They are not really constants as far as how the compiler treats them at compile time because they aren't -- they are just ReadOnly fields. But as far as your code is concerned in the IDE, they will act, feel and taste like constants.
It is the use of Const statement which limits how you can define them and require you to use (some) the VB functions rather than .NET ones.
Replace:
Public Const ctrM as Char = "\m"C
for this:
Public Const ctrM As Char = "m"c
Credits goes to Plutonix for giving a working/workable solution in a comment.
Used the following approach when I made large use of Modules long ago.
Add a Public Module to your Project :
Public Module MyConsts
' Define your constant Char
Public Const vbTabC As Char = Microsoft.VisualBasic.Chr(9) ' For Tabulation
Public Const vbEMC As Char = Microsoft.VisualBasic.Chr(25) ' For EM (End of Medium)
' ^^ if you know the ASCII Char Code.
' Use Microsoft.VisualBasic.ChrW() for Unicode (unsure of that)
Public Const vbCharQM As Char = "?"c
Public Const vbComma As Char = ","c
Public Const vbDot As Char = "."c
' or
Public Const vbCharQM2 As Char = CChar("?")
' ^^ if you can actually write the char as String in the Compiler IDE
End Module
Then use the constants identifier anywhere in your project like any VB constant string, but, they are of type Char of course (To combine them with String, you'll have to use .ToString())
Public Sub TestConstChar()
MessageBox.Show("[" + vbEMC.ToString() + "]")
' But hey ! What's the purpose of using End of Medium Char ?
End sub
Note that you have Environment.NewLine that automatically returns the valid Line Feed, or Carriage Return/Line Feed, or only Carriage Return, or even another control Char/String/Stream that is on use on your Operating System.
Based on the Environment.NewLine example, you can also define a (wandering) Class
Public Class MyConstChars
Public Shared ReadOnly Property Tab() As Char
Get
Return Microsoft.VisualBasic.ControlChars.Tab
End Get
End Property
' ...
End Class
' And use it anywhere like myString = "1" + MyConstChars.Tab.ToString() + "One"
This approach allows you to have more control over the actual value of the static/shared Property, like with Environment.NewLine, and allows your Class to propose much more options (Members) than a simple Constant. However, writing the LambdaClassName.LambdaClassProperty isn't very intuitive I reckon.
One another way to ease coding by using constant tags/identifiers in the IDE is to define Code Templates. A code template (piece of code) can be defined in the options of your IDE. You may already know what it is about : you type a keyword, then the IDE replace that keyword with one block of code (that you use often enough to require that shortcut) That's what is happening when you redefines (Overrides) a .ToString() Function in classes.
' I have for example one code template keyword...
PlaceholderChecker
' ...that generates the following Code :
#If IsDebugMode Then
''' <summary>
''' Placeholder Routine to check wether ALL Class Components are included in Solution.
''' </summary>
Private Shared Sub PlaceholderChecker()
p_ClassVariableName_ClassPartialSuffix = True
End Sub
#End If
In some cases, you don't have to define constants - or have to write more complex code - to get where you want.

EclipseLink - #ReadTransformer

I have this code:
#Column(name = "foo")
#ReadTransformer(transformerClass=transformer.class)
private Date foo;
public static class transformer implements AttributeTransformer {
#Override
public void initialize(AbstractTransformationMapping atm) {
}
#Override
public Object buildAttributeValue(Record record, Object o, Session sn) {
}
}
My question is, how do I get the value to transform (from column foo) inside of buildAttributeVaule? It is not inside the record array.
You need one or more #WriteTransformer to write the fields you want selected (and thus get them selected), #Column is not used with a transformation mapping.
However, if you just have a single column, then just use a converter instead, #Convert,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Basic_Mappings/Default_Conversions_and_Converters
First check that the SQL generated is reading in the "foo" column by turning on logging. If it is, then check that the database is returning "foo" and not "FOO" - java is case sensitive on string looksups. It could be that "FOO" is in the record instead of "foo".

LinQ to SQL and CLR User Defined Types

I have created a User Defined Type in .Net 3.5 as per my blog entry at :
http://jwsadlerdesign.blogspot.com/2009/04/this-is-how-you-register.html
This works fine when using SQL with technologies like nHibernate.
However, when I try to map my LinQ to SQL class to use this UDT (with attribute defintions not XML), and I setup the property as the enumeration. I cannot get LinQ to map to this type. I have tried Image, Binary, varchar and integer all of which seem to issue Invalid Cast errors.
In particular I get the error 'Unable to cast object of type 'ISTD.InstallManager.Common.Classes.SQLUDTTargetType' to type 'System.Byte[]' any ideas or help would be much appreciated.
James.
UPDATE: I ran into this myself recently and found that the previous solution wasn't quite complete. Despite what all of the documentation says, it is possible to do this, but somewhat painful.
The first step, for your own convenience, is to implement some conversion operators:
public class MyUDT : INullable, IBinarySerialize
{
// Class implementation would go here
// ...
public static explicit operator MyUDT(byte[] data)
{
using (MemoryStream stream = new MemoryStream(data))
{
using (BinaryReader reader = new BinaryReader(stream))
{
MyUDT result = new MyUDT();
result.Read(reader);
return result;
}
}
}
public static explicit operator byte[](MyUDT x)
{
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(ms))
{
x.Write(writer);
}
return ms.ToArray();
}
}
}
Linq to SQL will still flat-out refuse to give you the UDT field, no matter how you declare the property. So you have to give it a binary field instead. You don't need a stored procedure or any custom SQL for this, just add a computed column to your table:
ALTER TABLE MyTable
ADD UDTField_Data AS CAST(UDTField AS varbinary(len))
Where len is whatever your UDT defines in the MaxByteSize attribute.
Now you can finally get access to the column data. You might be tempted to use your UDT as the return type of the new property, thinking that Linq to SQL will find your conversion operator and automatically convert from the byte array; don't bother. Linq to SQL will decide that it's actually a serialized .NET object and spit out a message to the effect of "input stream is not a valid binary format." Instead, you need another layer of indirection:
private MyUDT udtField;
[Column(Name = "UDTField_Data", DbType = "varbinary(len)")]
private byte[] UdtFieldData
{
get { return (byte[])udtField; }
set { udtField = (MyUDT)value; }
}
public MyUDT UdtProperty
{
get { return udtField; }
set { udtField = value; }
}
A few notes to make it clear what's going on here:
The actual field data (udtField) is declared as the UDT itself, not a byte array. The reason for this is that we only want the conversion to happen when loading from or saving to the database. If you had to convert the byte array to the UDT every time you accessed it, it would not only hurt performance, but it would cause inconsistencies if the UDT declares any mutable fields.
The raw byte[] property (UdtFieldData) is declared private, so consumers only see the UDT itself. Linq to SQL will still read it as long as it has the [Column] attribute.
The UdtFieldData property does not declare a storage property. This is critical; if you try to use the UDT field as the storage property, you'll just get the same type conversion error.
Finally, the UdtProperty property is how consumers actually get to access the data. To them it looks like any other property.
It's unfortunate that you have to jump through so many hoops to get this to work, but it does work. You'll probably have difficulties doing this kind of massaging through the Linq surface designer, which is just one of several reasons why I don't use it; better to write the classes yourself and use SqlMetal to help you along if necessary.

(Fluent) NHibernate - Mapping Varchar to Int32

We work with legacy database which are saving integer values to the varchar column. We need to map this column to Int32 property and it works well if data in database column are numeric or NULL.
But we have problems if column contains empty string instead of null - nhibernate throws error that it cannot convert it to integer.
Is it possible to configure class mapping to automatically convert all values where the exception raises to some default value (zero in this case)?
It is probably possible to convert the values using an interceptor. You may get some advice by searching for "null value substitution".
But do you really have this need? You could map a private or read-only member for the varchar column and use a different property to control it.
private string _varcharField;
public string VarcharField
{
get { return _varcharField; }
}
public int IntProperty
{
get { [parse and return _varcharField]; }
set { _varcharField = value.ToString(); }
}
In this example, _varcharField would be mapped in NHibernate using an access strategy.

Dynamic Table Names in Linq to SQL

Hi all I have a horrid database I gotta work with and linq to sql is the option im taking to retrieve data from. anywho im trying to reuse a function by throwing in a different table name based on a user selection and there is no way to my knowledge to modify the TEntity or Table<> in a DataContext Query.
This is my current code.
public void GetRecordsByTableName(string table_name){
string sql = "Select * from " + table_name;
var records = dataContext.ExecuteQuery</*Suppossed Table Name*/>(sql);
ViewData["recordsByTableName"] = records.ToList();
}
I want to populate my ViewData with Enumerable records.
You can call the ExecuteQuery method on the DataContext instance. You will want to call the overload that takes a Type instance, outlined here:
http://msdn.microsoft.com/en-us/library/bb534292.aspx
Assuming that you have a type that is attributed correctly for the table, passing that Type instance for that type and the SQL will give you what you want.
As casperOne already answered, you can use ExecuteQuery method first overload (the one that asks for a Type parameter). Since i had a similar issue and you asked an example, here is one:
public IEnumerable<YourType> RetrieveData(string tableName, string name)
{
string sql = string.Format("Select * FROM {0} where Name = '{1}'", tableName, name);
var result = YourDataContext.ExecuteQuery(typeof(YourType), sql);
return result;
}
Pay attention to YourType since you will have to define a type that has a constructor (it can't be abstract or interface). I'd suggest you create a custom type that has exactly the same attributes that your SQL Table. If you do that, the ExecuteQuery method will automatically 'inject' the values from your table to your custom type. Like that:
//This is a hypothetical table mapped from LINQ DBML
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.ClientData")]
public partial class ClientData : INotifyPropertyChanging, INotifyPropertyChanged
{
private int _ID;
private string _NAME;
private string _AGE;
}
//This would be your custom type that emulates your ClientData table
public class ClientDataCustomType
{
private int _ID;
private string _NAME;
private string _AGE;
}
So, on the former example, the ExecuteQuery method would be:
var result = YourDataContext.ExecuteQuery(typeof(ClientDataCustomType), sql);