I created empty ArrayList of class objects and one class object. I added this class object with some parameters into ArrayList and then changed some parameters of this object. But class object that left in ArrayList also changed. That looks like I'm passing parameters by reference. Also, if I'm trying to create new object and make it equal with "=", that object becoming connected to old one, so if I'm changing first object then second one changing as well like reference to first variable. I've ran into same problem in Java (no surprise). So, how can I pass class object by value? I want to use one class object to add new objects into ArrayList and then change it without changing class object inside ArrayList.
class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
classObject.someData = 5
testArrayList.add(classObject)
classObject.someData = 7
testArrayList.add(classObject)
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData) //Output = 777. Needed 357
}
Same with creating new objects
class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
var secondClassObject : TestClass = classObject
testArrayList.add(secondClassObject)
classObject.someData = 5
var thirdClassObject : TestClass = classObject
testArrayList.add(thirdClassObject)
classObject.someData = 7
var fourthClassObject : TestClass = classObject
testArrayList.add(classObject)
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData) //Output = 777. Needed 357
}
You try to make similar code in Java because arrayList in Java works the same in this situation. So, you can send answer in Java code
You are basically adding the same instance of TestClass over and again with modified value, so the instances in array position 3 will also point to same instance of 1, if you really want different values, you need to either create a different instances, or use data class with copy which copies the values into different instance and you can named parameters to change values you need as below
data class TestClass(var someData : Int = 0)
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
testArrayList.add(classObject.copy(someData = 5))
testArrayList.add(classObject.copy(someData = 7))
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData)
}
copy
To copy an object for changing some of its properties, but keeping the
rest unchanged, use the copy() function.
class TestClass(var someData : Int = 0) {
fun copy(someData: Int = this.someData) = TestClass(someData)
}
fun main(){
var testArrayList = arrayListOf<TestClass>()
var classObject : TestClass = TestClass(3)
testArrayList.add(classObject)
testArrayList.add(classObject.copy(someData = 5))
testArrayList.add(classObject.copy(someData = 7))
print(testArrayList[0].someData)
print(testArrayList[1].someData)
print(testArrayList[2].someData)
}
Related
I would like to repeatedly enter a number that is added to a linked list.
But there's an error in the code at line x = new Node():
No enclosing instance of type Main is accessible. Must qualify the allocation with an enclosing instance of type Main (e.g. x.new A() where x is an instance of Main).
Is there a way to fix my code?
static Node head;
static Node p;
static Node q;
static Node x;
class Node {
int data;
Node next;
public Node link;
// Constructor to create a new node
// Next is by default initialized
// as null
Node(int d) {
data = d;
next = null;
}
public Node() {
// TODO Auto-generated constructor stub
}
}
Two issues:
class Node should either be declared as static, or be moved to a separate file.
p = x should happen outside the else block, since it should get this value also when the if condition was true:
if(head == null) {
head = x;
} else {
p.link = x;
}
p = x;
Some remarks:
If you really want to use the Node constructor without arguments, then it is better to define explicitly what the new Node's properties should be:
public Node() {
data = 0;
next = null;
}
However, it would be better to not have this constructor signature at all, and only construct the object using the data as argument:
if(num != -999){
x = new Node(num);
...and now you don't need to do any of this any more:
x.data = num;
x.link = null;
The inner Node class is not static, meaning it belongs to a specific instance of the enclosing Main class. Since it doesn't refer to any instance methods this seems like it was not done intentionally. Make the class itself static (i.e., static class Node {) and you should be fine.
First, the class Node cannot be referenced from a static context. To fix this, make it static or move it to its own file. Second, the null pointer exception happens since you don't assign p in the special case where the list is empty.
Overall, I suggest that you clean up your class and use a more structured approach. Rename p to last to make it clear that this is a reference to the last element of the list. Move the functionality to add a node into its own method to make the code more readable. Use next in the Node class to point to the next node instead of link. Create an instance of the class where your head and last reference is defined and make them private. Use break inside the loop to only define the magic number (-999) once and exit the loop when it is entered.
The whole class could look like this:
public class CustomLinkedList {
private Node head = null;
private Node last = null;
static class Node {
int data;
Node next = null;
}
public void add(int num) {
Node x = new Node();
x.data = num;
if (this.head == null) {
this.head = x;
} else {
this.last.next = x;
}
this.last = x;
}
public static void main(String[] args) {
CustomLinkedList list = new CustomLinkedList();
int count = 0;
do {
try {
BufferedReader dataIn = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Enter number " + (++count) + ": ");
String strNum = dataIn.readLine();
int num = Integer.parseInt(strNum);
if (num != -999) {
list.add(num);
} else {
break; // exit loop
}
} catch (IOException e) {
System.out.print(e.getMessage());
}
} while (true);
}
}
I am trying to use reflection and ninject on the same project. Here is my code :
Type type = Type.GetType("MySolution.Project.Web.App_Code.DataClass");
MethodInfo theMethod = type.GetMethod("Events_ListAll");
object classInstance = Activator.CreateInstance(type, null);
And here is my class that contains that method:
public class DataClass
{
private IEventService eventService;
public DataClass(IEventService eventService)
{
this.eventService = eventService;
}
public String Events_ListAll()
{
List<Event> lstEvents = eventService.GetEvents().ToList<Event>();
return "";
}
}
I get an error saying that there is no constructor found. The solution to that would be to ad an empty default constructor, but that wont inject class I want. Is there any workaround to solve this?
You will need a concrete instance of IEventService to pass as parameter to ctor of DataClass, like this Activator.CreateInstance(type, instance);, so you got many approaches to do that, see 2 of :
1st - class has a concrete IEventService
That class where you doing the reflection has a concrete instance of IEventService and then you just pass as param to the Activator:
public class Foo
{
public Foo(IEventService eventService)
{
Type type = Type.GetType("MySolution.Project.Web.App_Code.DataClass");
MethodInfo theMethod = type.GetMethod("Events_ListAll");
object classInstance = Activator.CreateInstance(type, eventService);
}
}
2nd - Get IKernel implementation of Ninject
If you are using NinjectWebCommom you can just change the bootstrapper prop to public and get the kernel like this NinjectWebCommom.bootstrapper.Kernel.get<IEventService>()
Type type = Type.GetType("MySolution.Project.Web.App_Code.DataClass");
MethodInfo theMethod = type.GetMethod("Events_ListAll");
object classInstance = Activator.CreateInstance(type, Kernel.Get<IEventService>());
So the problem is as follows. I am unit testing a class SampleClass using Rhino Mocks 3.6. For the tests I use a mock of InnerClass as it is used in the SampleClass constructor. InnerClass has a method called TheMethod(ref string s1,ref string s2). Here is where the problem begins. TheMethod(ref string,ref string) is doing nothing with the parameters and I want TheMethod to actually modify one of the strings (s1). Is it possible, using Rhino Mocks, to do such thing? If so, then how? WhenCalled? Do() handler? I'm clueless. Here's the pseudocode
Class SampleClass
{
Public String SampleClassMethod()
{
string s1 = string.Empty;
string s2 = string.Empty;
string s_final = this.InnerClass.TheMethod(ref s1, ref s2); //TheMethod() which is doing
//nothing with the given strings
if (s_final == "something")
return s1;
}
}
The result is, that s1 is unchanged and for the testing reasons I would like the TestMethod() to modify s1's value WITHOUT changing the body of TheMethod() itself
[TestMethod]
public void TestMethod1()
{
//generating mocks
//SampleClass target; //tested class object
Expect.Call(InnerClassMock.TheMethod(
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy,
ref Arg<string>.Ref(Rhino.Mocks.Constraints.Is.Equal(s1), string1).Dummy)).IgnoreArguments();
string temp = target.SampleClassMethod();
Assert.AreEqual("1234", temp);
}
Assuming your inner class looks something like this (Note that TheMethod is virtual):
public class SomeClass
{
public virtual string TheMethod(ref string s1, ref string s2)
{
s1 = "X";
s2 = "Y";
return "Z";
}
}
You can use Rhino.Mock's "OutRef" option to define output for ref arguments:
var mock = MockRepository.GenerateStub<SomeClass>();
string temp1 = "", temp2 = "";
mock.Stub(m => m.TheMethod(ref temp1, ref temp2)).OutRef("AAA", "BBB").Return("DEF");
var my1 = "";
var my2 = "";
var result = mock.TheMethod(ref my1, ref my2);
After running this code, my1 will be "AAA", my2 will be "BBB" and result will be "DEF".
As part of my project, I am trying to build a web UI where user will select a method and pass the values. My program should be able to call the method dynamically and build a parameter list on runtime to pass it to the method.
I have created a comma separated list (string) of key and value pairs. This key/value pair is nothing but the parameter name and value of my method (methodname stored in a variable). Example: string params = "ID:123;Name:Garry;Address:addressObject;AddressLine:108 Plaza Lane;City:Avenel;State:NJ;Zip:07001;". Where ID and Name are simple string varaibles while Address is user defined type. What follows after Address i.e. AddressLine, City, State and Zip is elements of Address object. And my method definition is
public string GetInfo(string ID, string Name, Address addressObject)
{
//return something;
}
I am dynamically calling the method (GetInfo) that is stored in sMethodName variable using DynamicProxy like :
string sMethodName = "GetInfo";
object result = (object) proxy.CallMethod(sMethodName, arguments);
Challenge is how to pass the argument list dynamically? Till now I am just able to extract the values from the csv variable into NamedValueCollection. Here is the code:
public static void StoreParameterValues(string param)
{
nvc = new NameValueCollection();
param = param.TrimEnd(';');
string[] parameters = param.Split(new char[] { ';' });
foreach (string val in parameters)
{
string[] keyValue = val.Split(new char[] { ':' });
nvc.Add(keyValue[0], keyValue[1]);
}
}
..and here is the code that tries to build the parameter:
string methodName = "GetInfo";
DynamicProxyFactory factory = new DynamicProxyFactory("http://../myservice.svc");
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name;
}
DynamicProxy proxy = factory.CreateProxy(sContract);
string[] values = null;
// Create the parameter list
object[] arguments = new object[nvc.Count];
int i = -1;
foreach (string key in nvc.Keys)
{
values = nvc.GetValues(key);
foreach (string value in values)
{
arguments[++i] = value;
}
}
object result = (object) proxy.CallMethod(methodName, arguments);
The above code works if I have simple primitive types but not sure how can I build the logic for any other userdefined types. How can I create a object dynamically of type stored in a variable? Not sure if I was able to put my question correctly. I hope so :)
Edit: 01/19/2011: Applied the suggestion from Chris - using Reflection instead of ComponentModel.
I have converted the code to make it more generic. This works now for all primitive and custom types (resursion). Code snippet below:
private object BuildParameterList(Type type)
{
object item = new object();
item = Activator.CreateInstance(type);
PropertyInfo[] propArray = type.GetProperties(BindingFlags.Public|BindingFlags.Instance);
for (int i = 0; i < propArray.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propArray[i];
////Check for custom type
if (IsCustomType(pi.PropertyType))
{
object item1 = BuildParameterList(pi.PropertyType);
pi.SetValue(item, item1, null);
}
else
{
if (property.ContainsKey(pi.Name))
{
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
}
}
}
return item;
}
But if one of the property is Color (I just tested with Color type, will fail with other system types aswell-i guess), then it fails at the following line. Not sure how to handle system types - Color or something similar.
pi.SetValue(item, Convert.ChangeType(property[pi.Name], pi.PropertyType), null);
Can you not find what types are expected by the method, by inspecting its ParameterInfos:
endpoint.Contract.ContractType.GetMethod(methodName).GetParameters();
and then instantiating the custom types using:
Activator.CreateInstance(parameterType);
I'm somewhat new to object oriented programming in Javascript and I'm trying to build a handler object and library for a list of items I get back from an API call. Ideally, I'd like the library functions to be members of the handler class. I'm having trouble getting my class method to work however. I defined as part of the class bcObject the method getModifiedDateTime, but when I try to echo the result of the objects call to this method, I get this error:
Error on line 44 position 26: Expected ';'
this.getModifiedDateTime: function(epochtime) {
which leads me to believe that I simply have a syntax issue with my method definition but I can't figure out where.
response(
{
"items":
[
{"id":711,"name":"Shuttle","lastModifiedDate":"1268426336727"},
{"id":754,"name":"Formula1","lastModifiedDate":"1270121717721"}
],
"extraListItemsAttr1":"blah",
"extraListItemsAttr2":"blah2"
});
function response(MyObject) {
bcObject = new bcObject(MyObject);
thing = bcObject.getModifiedDateTime(bcObject.videoItem[0].lastModifiedDate);
SOSE.Echo(thing);
}
function bcObject(listObject) {
// define class members
this.responseList = {};
this.videoCount = 0;
this.videoItem = [];
this.responseListError = "";
// instantiate members
this.responseList = listObject;
this.videoCount = listObject.items.length;
// populate videoItem array
for (i=0;i<this.videoCount;i++) {
this.videoItem[i] = listObject.items[i];
}
this.getModifiedDateTime: function(epochtime) {
var dateStringOutput = "";
var myDate = new Date(epochtime);
dateStringOutput = myDate.toLocaleString();
return dateStringOutput;
};
}
You use = to assign values in JS, not ::
this.getModifiedDateTime = function(epochtime) {
You should use the = operator for methods defined as you did there (this.<methodName> = function (...) {).
The colon notation is used when declaring object literals.