In a script I want to create an object of a class only if all the constructor inputs meet some conditions. All the checks are embedded in the constructor itself. Problem is when:
myObj = myClass(input1,input2,...);
is triggered in the script. The object, even when an input doesn't meet the relative condition, is still created eventually with all empty properties.
Inserting the following code within the constructor:
if nargout == 0
clear obj;
end
prevents the creation of the object, but only when the output is assigned to the ans variable. Otherwise, I get an error.
Is there a way to obtain something like that without adding some code directly into the script (like using try)?
If the constructor throws an error, no object will be created. Use error. You can put a try/catch block around the constructor call if you like.
There is no way AFAIK to have the constructor return normally but produce no object. What would be assigned to its output?
I am trying to understand the concept of why struct vs. class have difference results. Why is the result the same here but different on structs:
import UIKit
class Message {
var internalText: String = "This is some text"
}
// create new instance
var firstMessage = Message()
//if I assign, its a reference to the original instance
var secondMessage = firstMessage
secondMessage.internalText += " with some more text added on."
//print both
print(firstMessage.internalText)
print(secondMessage.internalText)
output:
This is some text with some more text added on.
This is some text with some more text added on.
Now if you change the above from declaration from "class" to "struct"
struct Message {
var internalText: String = "This is some text"
}
...
output becomes:
This is some text
This is some text with some more text added on.
Why in the class declaration does it change the firstMessage object. Are they the same objects? Is this a rule that if I assign a new object from the old object? Then I would have to declare secondMessage = Message() to make it a new instance.
Thanks in advance.
In Swift, classes are reference types, whereas structs are value types. Value types are copied on variable assignment, whereas reference types are not.
More explanation
The system stores instantiated classes and structs into the memory. There are two main sections of the memory involved in the storage of data, the stack, and the heap. The stack contains the local variables introduced in the current method or function, and the heap is used as a kinda external memory, storing larger values. The program can only access variables stored in the stack, so a reference to the value in the heap should be held in the stack.
When you instantiate a class object by using something like Message(), a free space is reserved in your memory's heap and a reference to it is held in the stack. When you assign the same variable to a new one, the reference is copied and both variables will refer to the same bytes in the heap, so changing one changes another too.
When using structs, all the space is being reserved on the stack and there is no such thing as a pointer or reference, so when assigning to a new variable, all the data gets copied (in fact, the system is smart enough to only copy the necessary values which are being changed).
You can see a nice tutorial covering these subjects here.
Why in the class declaration does it change the firstMessage object. Are they the same objects?
The example you gave is a really nice one because it succinctly illustrates the difference between class and struct, and you came about this close -> <- to answering your own question, even if you didn't realize it. As the other answers have explained, class creates a reference type, which means that when you assign an instance of a class to a variable, that variable gets a reference to the object, not a copy of it. You said so yourself:
//if I assign, its a reference to the original instance
var secondMessage = firstMessage
In your example, firstMessage and secondMessage are really references to the one object that you created. This kind of thing is done all the time in object oriented languages because it's often important to know that you're dealing with a specific object and not a copy, especially if you might want to make changes to that object. But that also brings danger: if your code can get a reference to an object and change it, so can some other code in the program. Shared objects that can be changed create all kinds of headaches when you start writing multithreaded code. When you added text to secondMessage, firstMessage also changed because both variables refer to the same object.
Changing the declaration of Message to struct makes it a value type, where assignment (for example) creates a new copy of the object in question instead of a new reference to the same object. When you added text to secondMessage after changing Message to a struct, the assignment secondMessage = firstMessage created a copy of firstMessage, and you only changed that copy.
Is this a rule that if I assign a new object from the old object?
Whether your assignment creates a copy of the object or a reference to it depends, as you've shown, on whether the thing being assigned has reference semantics (class) or value semantics (struct). So you need to be aware of the difference, but most of the time you don't need to think too hard about it. If you're dealing with an object where you don't care about the object's identity and are mainly concerned with its contents (like a number, string, or array), expect that to be a struct. If you care about which object you're dealing with, like the front window or the current document, that'll be a class.
Then I would have to declare secondMessage = Message() to make it a new instance.
Right -- if Message is a class, assigning one to a new variable or passing it into a method won't create a new one. So again, are you more likely to care about which message you're dealing with, or what is in the message?
Simple answer: Classes are reference types Structs are value types.
In the class, firstMessage is set to Message() which is an instance of the whole class Message. So when secondMessage gets set to equal firstMessage, secondMessage Doesn’t make a new class again, it just makes a note of where firstMessage is at and they both can now operate it. But because they both in the same location, the internalText will be the same for both.
While with the struct, since they are value types, secondMessage copies all the values from firstMessage and creates its own independent object of type Message.
Classes are reference types, meaning that the firstMessage and secondMessage variables you defined in your first snippet stores only a reference to the class instance you created. Imagine your object is located somewhere in your memory heap with an id (for example, id0001), then both firstMessage and secondMessage stores only the id, which is id0001, so they both refer to the same object in memory.
On the other hand, structs are value types, meaning that the struct variables store unique objects directly; unlike reference types, no sharing is going on. So when you are assigning a new struct variable to a previous struct variable, the object gets copied, and the two variables store two unique objects with different memory addresses (IDs).
For more information, check out the official doc on classes and structs.
Let us understand the same concept with an example,
Suppose you have a google sheet in which you are adding some text and at a time you share that sheet to some other person for editing or deleting purpose. So when the other person do any changes you can see at a time. This concept is followed in class.
Moreover, classes are reference types because here you are passing a reference(sheet).
However, you have downloaded that google sheet and send its copy to another person so at that time you are not able to see the changes until and unless the person sends back the sheet. And this is the same concept followed in struct. A struct is value type because we are passing a copy(downloaded sheet).
We can inherit class but cannot inherit struct
Think of structs as a Microsoft Excel file. You create a copy and send it to me. When I change my copy, your copy doesn't get changed.
Classes on the other hand are more like Google Sheets. When I make changes to the file you shared with me, you can see the changes.
Instances of structs make copies and have different places in memory
Instances of classes point to the same place in memory
In dart I can create an object and call a method in two ways:
First one:
ClassA a = new ClassA();
a.methodA();
Second one:
new classA().methodA();
Does it have any negative effect to keep doing this? Let's say I want to call 4-5 methods from ClassA in another class, would it have any negative effects, f.x. on performance by using the second way?
That's still the exact same object creation process, it's just a simple constructor call. The only difference is that in one case you're giving the result a name (a), in the other you're not.
It's not like you're saving memory by not saving the object to a variable. In either case, a reference to your new ClassA object needs to exist somewhere, (whether explicitly named or not), otherwise how would methodA know which object to operate on?
However, there is a difference between:
ClassA a = new ClassA()
a.methodA()
a.methodB()
a.methodC()
a.methodD()
a.methodE()
versus
new ClassA().methodA()
new ClassA().methodB()
new ClassA().methodC()
new ClassA().methodD()
new ClassA().methodE()
In the first case, you're reusing the same object a (from a single constructor call) as a target of all 5 instance method calls. In the latter case, you have 5 distinct objects (from 5 separate constructor calls), each as a target of a single method call. These can obviously have very different semantics.
After evolving my project code for months, I've finally hit a need to define a new class. Having to romp through my previous class definitions as a refresher of the conventions, I noticed that all constructors and property setters all have an output argument, even though nothing is assigned to it, e.g.:
function o = myConstructor( arg1, arg2, ... )
function o = set.SomeProperty( o, arg1 )
I've been looking through the documentation for upward of an hour without finding the explanation for this. It doesn't look like it depends on whether a function is defined in the class definition file or in its own separate m-file.
Can anyone please explain?
The best place to start is the documentation "Comparison of Handle and Value Classes". From the very top:
A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLAB® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument.
A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.
In other words, value classes need to return a modified object (which is a new object distinct from the original), while handle classes don't. The constructor of either class will always have to return an object, since it is actually constructing it.
Some good additional reading is "Which Kind of Class to Use", which links to a couple helpful examples of each type of class object. Looking at the DocPolynom value class example, you can see that property set methods have to return the modified object, while the dlnode handle class example only requires an output for its constructor. Note that you could still return an object from a handle class method (if desired), but it's not required.
I have a classe derived from matlab.mixin.Copyable. Some of the properties have set methods. I want the setting of those properties to also update other properties so that the relationship between the parameters are consistent (a classic use of set methods).
Unfortunately, when I load a *.mat file [specifically using, say, x=load('file.mat')], setters are also used. There should be no need for that kind of automatic update of multiple parameters, since all the object's properties can be copied from the *.mat file and self-consistency is automatically maintained. Instead, using setters during load causes errors because the setter uses other properties that haven't yet been assigned to in the load process. I see this from error that occurs during the load, and from checking the properties that are needed by the setter.
Is there any way to force the load to do a simple replication of the property values contained the *.mat file? Some of the properties are complex objects themselves, so what's needed is a recursive copy-by-value during load. It seems rather inappropriate to use setters during a load, for the reasons above.
P.S. I say above that the setter uses another as-yet-unassigned property. Let's call this property p2. It also gets assigned to by a setter for 3rd property s1. It seemed odd, but s1 does have a value, while p2 does not. One possible reason is that p2 relies on other properties in addition to s1, and those might not have been assigned to when s1 is loaded (i.e., when the s1 setter is invoked). The whole problem stems from the fact that load occurs outside of the context and the order in which properties are assigned to during the execution of the code that created it. This is the key reason why (it seems to me that) load should not use setters. Otherwise, it seems to be incompatible with either copying or loading (I'm not sure which at the moment -- maybe both).
The process MATLAB uses to load objects is well documented. This page mentions, among many other things, that the set methods are called to prevent issues that happen when a class definition changes, and you try to load an object from that class from an old file.
There is also a page explaining how to modify the save and load process. This page describes the use of loadobj, defined as a static method to your class, to change how the object is constructed from the information in the file. loadobj is called when one of the set methods throws an error; but it is always called if saveobj returns a struct. That is, one solution to your problem is to have saveobj create a struct with all the data, and have loadobj reconstruct your object from that struct.
This other documentation page describes how to design your class to avoid property initialization order dependency -- which is the problem you describe having. The way to do this is to have all public properties be dependent properties, with the "actual" data properties being hidden and not interdependent. You might be able to construct your class this way, for example with a single data property (a cell array or struct), which would be loaded and saved in one go, and the public properties simply using a portion of this cell or struct in the set and get methods.