Consider the following code where I wish to store instances of a class (Class2 here) and its derived classes (Class3 here) in an array residing in another class (Class1 here). As notated, the compiler is not happy with the final line. What am I doing wrong?
class Class2 {
var y : int;
}
class Class3 : Class2 {
var z : int;
}
class Class1 {
var count : int;
var x : [0..10] owned Class2?;
proc add(ref a : Class2) {
x[count] = a;
count += 1;
}
}
var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();
C1.add(C2); // OK
C1.add(C3); // Compiler not happy
Compiler output:
test2.chpl:25: error: unresolved call 'owned Class1.add(owned Class3)'
test2.chpl:14: note: this candidate did not match: Class1.add(ref a: Class2)
test2.chpl:25: note: because call actual argument #1 with type owned Class3
test2.chpl:14: note: is passed to formal 'ref a: owned Class2'
$CHPL_HOME/modules/internal/Atomics.chpl:557: note: candidates are: AtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
$CHPL_HOME/modules/internal/NetworkAtomics.chpl:280: note: RAtomicT.add(value: T, param order: memoryOrder = memoryOrder.seqCst)
note: and 4 other candidates, use --print-all-candidates to see them
Try using the in intent instead of the ref intent on proc add:
class Class2 {
var y : int;
}
class Class3 : Class2 {
var z : int;
}
class Class1 {
var count : int;
var x : [0..10] owned Class2?;
proc add(in a : Class2) {
x[count] = a;
count += 1;
}
}
var C1 = new owned Class1();
var C2 = new owned Class2();
var C3 = new owned Class3();
C1.add(C2); // OK
C1.add(C3); // OK!
Why does this matter? It's not type-safe to pass a reference to a subclass (Class3) to an argument expecting a reference to a parent class (Class2). In particular you could imagine the method changing the class pointer to be a Class2 but not a Class3, and that could lead to other errors at the call site.
My guess is that the add function was using the ref intent just to enable ownership transfer from C3. The in intent is a better way to do that and supports passing a subtype (because the type error situation described above is not possible).
Related
I have two ArrayLists of different Data classes as given below:
class Record{
var id: Long = 0
var RecordId: Int = 0
var Record: String? = null
var title: String? = null
var description: String? = null
var longDate: Long = 0
}
class Type{
var id: Long = 0
var typeId: Int = 0
var subTypeId: Int = 0
var typeString: String? = null
var longDate: Long = 0
}
var recordsList: ArrayList<Record>
var typesList: ArrayList<Type>
Now, I want a merged list of these two which will be sorted based on a common field in both the Objects i.e. longDate. I have tried .associate , sortedBy, sortedWith(compareBy<>) etc. but could not achieve the desired result.
Here, also there is one point to note is that while comparing the two lists it is possible that one on them may be empty.
This will produce a List<Any> with all items sorted by longDate:
(recordsList + typesList)
.sortedBy {
when (it) {
is Record -> it.longDate
is Type -> it.longDate
else -> error("")
}
}
Or you might consider creating an interface that has val longDate: Long that both of these classes implement. Then you wouldn't need the when expression, and your List would be of the type of the interface.
Something like this should work, but I personally think that it is quite the code smell. There is no guarantee that Record.longDate is truly the same type as Type.longDate (we know that it is, since we create the model, but the compiler would never know).
val result = (recordsList + typesList).sortedBy {
when(it){
is Record -> it.longDate
is Type -> it.longDate
else -> error("incompatible list element $it")
}
}
And it would work something like this: (I've removed some parameters from the models as they don't really count here)
fun main() {
val recordsList = listOf(Record().apply { longDate = 5 }, Record().apply { longDate = 3})
val typesList = listOf(Type().apply { longDate = 3 }, Type().apply { longDate = 2 })
val result = (recordsList + typesList).sortedBy {
when(it){
is Record -> it.longDate
is Type -> it.longDate
else -> error("incompatible list element $it")
}
}
result.forEach{
println(it.toString())
}
}
class Record{
var longDate: Long = 0
override fun toString(): String {
return "Record(longDate=$longDate)"
}
}
class Type{
var longDate: Long = 0
override fun toString(): String {
return "Type(longDate=$longDate)"
}
}
This will output:
Type(longDate=2)
Record(longDate=3)
Type(longDate=3)
Record(longDate=5)
Doing it in a more generic way, so that you can create a fun where you state which property to be used from each object type would most likely use reflection, which I'd avoid at all costs.
So I would definitely consider if one object can inherit the other, or create an interface, or anything else.
I'll end with 2 questions: why no constructors? why ArrayList and not list?
is there a way to get an object from a collection of a specific subtype when subtype is only known at run time? something like:
class A
{}
class B : A
{}
class C : A
{}
Main()
{
List<A> outsideList = new List<A>() {new A(), new B(), new C()};
foreach(var ojb in outsideList)
{
dosomethingwithanobject(ojb);
}
}
void dosomethingwithanobject(A obj)
{
List<A> intenalList = new List<A>() { new C(), new A(), new B()};
// this can be A, B or C
type DESIREDTYPE = typeof(obj);
var item = list.GetSubType<DESIREDTYPE>().FirstOrDefault();
// do something with the item
}
I think you can use the the following code:
var result = intenalList.Where(x => x.GetType() == obj.GetType()).FirstOrDefault();
LINQ has two operations for transforming a sequence of unknown (or parent) types to subtypes: Cast and OfType.
Cast applies the type conversion to each element and fails if it is invalid.
OfType only returns the elements that can be converted to the new type.
So,
var item = list.OfType<DESIREDTYPE>().FirstOrDefault();
I need to get in R a list of objects from Java. In the code below I succeeded in getting the list in R (the length of the list is correct) but I cannot see the objects content.
This class represents the objects:
package mypackage;
public class ValueObject
public String s;
public int i;
}
This class returns the list of objects:
package mypackage;
public class MyClass {
public ValueObject [] test(){
ValueObject [] array = new ValueObject [3];
ValueObject a = new ValueObject();
a.i = 1;
a.s = "A";
array[0] = a;
ValueObject b = new ValueObject();
b.i = 2;
b.s = "B";
array[1] = b;
ValueObject c = new ValueObject();
c.i = 3;
c.s = "C";
array[2] = c;
return array;
}
}
And I run it in R, like so:
obj = .jnew("mypackage/MyClass")
x = .jcall(obj,"[Lmypackage/ValueObject;","test")
print(length(x)) shows 3, meaning that the objects are there. But I can't figure out how to access the data in the objects. I tried:
x[1]$s
x[1]["s"]
x[1]#s
and always get NULL. what's wrong with this code?
this does the trick:
print(x[[1]]$s)
I have a datatable with 100,000+ DataRow. Which method is faster to access the collection?
Is there any faster way to process the rows collection ?
Method 1:
var rows= dsDataSet.Tables["dtTableName"].Rows;
int rowCount = dsDataSet.Tables["dtTableName"].Rows.Count;
for (int c = 0; c < rowCount; c++)
{
var theRow = rows[c];
//process the dataRow
}
Method 2:
for (int c = 0; c < dsDataSet.Tables["dtTableName"].Rows.Count; c++)
{
var theRow = dsDataSet.Tables["dtTableName"].Rows[c];
//process the dataRow
}
It is worth noting the most direct way to access cells is via the DataColumn indexer; the data is actually stored in the columns, not the rows (no: really).
So something like:
var table = dataSet.Tables["dtTableName"];
// HERE: fetch the DataColumn of those you need, for example:
var idCol = table.Columns["Id"];
var nameCol = table.Columns["Name"];
// now loop
foreach(DataRow row in table.Rows)
{
var id = (int)row[idCol];
var name = (string)row[nameCol];
// ...
}
However, frankly if you want the best performance, I would start by saying "don't use DataSet / DataTable". That is actually a very complicated model designed to be all kinds of flexible, with change tracking, rule enforcement, etc. If you want fast, I'd use a POCO and something like "dapper", for example:
public class Foo {
public int Id {get;set;}
public string Name {get;set;}
}
...
string region = "North";
foreach(var row in conn.Query<Foo>("select * from [Foo] where Region = #region",
new { region })) // <=== simple but correct parameterisation
{
// TODO: do something with row.Id and row.Name, which are direct
// properties of the Foo row returned
var id = row.Id;
var name = row.Name;
// ...
}
or even skip the type via dynamic:
string region = "North";
foreach(var row in conn.Query("select * from [Foo] where Region = #region",
new { region })) // ^^^ note no <Foo> here
{
// here "row" is dynamic, but still works; not quite as direct as a
// POCO object, though
int id = row.Id; // <=== note we can't use `var` here or the
string name = row.Name; // variables would themselves be "dynamic"
// ...
}
I am working on LINQ. and in one transaction I have to update three different tables.
e.g A(A1,A2,A3) B(B1,B2) AB(A1,B1)
here B1 is autonumber in my database. I want to submit all the changes together. so in one data context I wrote
using (BBBDataContext DC= new BBBDataContext())
{
A tba = new A()
{
A1 = this.A1,
A2 = this.A2,
A3 = this.A3,
};
DC.A.InsertOnSubmit(tba);
B tbb= new B()
{
B2 = this.B2,
};
DC.B.InsertOnSubmit(tbb);
// NOW i WONT B1(WHICH IS AUTONUMBER) FROM B SO THAT I USE IT IN MY NEXT TABLE.
AB tbab = new AB()
{
A1 = this.A1,
B1 = ??????,
};
DC.AB.InsertOnSubmit(tbab);
//FINALLY I WILL WRITE SUBMIT CHANGES SO MY ALL TABLES GET CHANGES SAME TIME
DC.SubmitChanges();
}
Que: what should I write # the place of ?????. for B1 in AB table??
Short answer: B
Bit longer answer:
When you create the object and add it you won't get the ID before you commit. So what you do is reference the object and not the ID property of the object.
class A {
public int Id { get;set;}
public ICollection <B> Bees { get;set;}
}
class B {
public int Id { get;set;}
public int InstanceOfAId { get;set;}
public A InstanceOfA { get;set;}
}
var a = new A();
var b = new B();
b.InstanceOfA = a;
Depending on your model you will define a relationship. In code first you could do it this way:
EntityTypeConfiguration<B> cfgB = new EntityTypeConfiguration<B>();
cfgB.HasRequired(p => p.InstanceOfA).WithMany(p => p.Bees)
.HasForeignKey(p => p.InstanceOfAId);
In EDMX you can do the same in the designer.
You will use InstanceOfA to assign to when inserting, after that InstanceOfAId will always hold the Id value. When retrieving data InstanceOfA will only be filled when requested.
You can use it like this:
var x = DC.B.Include(p=>p.A);
or
var x = DC.B.Select(p=> new { Id = p.Id, A_Id = p.A.Id});
or
var x = DC.A.Select(p=> new { Id = p.Id, BeeCount = p.Bees.Count()});