difference between NSObject and Struct - struct

I want to know the difference between the NSObject and struct..Following example will explain both cases
In struct
struct UserDetails{
var userName:String
var userID:String
var userAge:String
func userDescription()->String{
return "name " + userName + "age " + userAge
}
}
In NSObject Class
class UserDetails: NSObject {
var userName:String?
var userID:String?
var userAge:String?
func userDescription()->String{
return "name " + userName! + "age " + userAge!
}
}
Can you anyone please tell me where I have to use NSObject class, where I have to use struct..?

1) Structs are passed by value, Class instances by reference
2) Classes can be subclassed, Structs can't.
Whether or not the Class is a subclass of NSObject is (mostly) irrelevant. You could equally have said:
class UserDetails {
var userName:String?
var userID:String?
var userAge:String?
func userDescription()->String{
return "name " + userName! + "age " + userAge!
}
}

Classes and structs in Swift are much closer than in many languages. Both can have properties, method, initializers, subscripts, can conform to protocols, and can be extended. However, only classes can take advantage of inheritance and use deinitializers, and because classes are used by reference, you can have more than one reference to a particular instance.
Structs are used throughout Swift -- arrays, dictionaries, everything optional, and more are built on the struct type, so performance should be very high. You can use struct whenever you don't need the inheritance or multiple references that classes provide.

Related

Restricting the type on function argument in Node.js and TypeScript

Working on a Node.js project and using TypeScript.
I'm trying to restrict a functions argument type to a specific base class. I'm new with both Node & TypeScript and come from a C# background, so likely not quite understanding some of the characteristics of the lang.
Take these snippets.
First, my class declarations
class DTO{
}
class userDTO extends DTO{
#IsDefined({message:"Username required"})
#Expose()
#Length(1,10, {message:"min 1 max 10"})
username:String;
}
class badDTO {
name:String;
}
Now I will create instances:
let user = new userDTO();
user.username = "My username";
let isUserDTO = user instanceof DTO; // Evaluates true
let bad = new badDTO();
bad.name = "Bob";
let isBadDTO = user instanceof DTO; // Evaluates false
Here is the signature of the method I intend to call
export default function ValidateDTO(objToValidate:DTO, validateMissingProperties:boolean): Array<string>{
return [];
}
Finally, when I actually call the function.
let userErrors = ValidateDTO(user, true);
// Why is this allowed?
let badErr = ValidateDTO(bad, true);
I am expecting the 2nd ValidateDTO to show me a warning and not actually run because 'bad' is not a DTO as proven by instanceOf above - if i try passing a string as the 2nd arg I see an error, which is what i expected from passing a non-DTO as the first arg.
Can someone please show me where I am going wrong? How can I restrict the type of object passed into a function.
Happy to share other code as required too. Not sure what else i might be missing.
You're not at all alone being surprised by this. :-) One of the key things about the TypeScript type system is that it's structural (based on structure), not nominal (based on names). As long as something has the minimum structure necessary, it matches even if it has a different ancestry. That means any object will be accepted by the type system as your DTO type because your DTO type has no properties, so all objects match it.
That's mostly a feature, but sometimes you want to disable it. The usual approach when you want to disable it is to use a branding property:
class DTO {
__brand = "DTO" as const;
}
Now, only objects that have a __brand property with the value "DTO" will be allowed where DTO objects are expected by the type system.
Here's a complete example with some minor changes to be more in keeping with JavaScript/TypeScript naming conventions and to supply some bits that were missing in the question code (presumably to keep it short! :-) ):
class DTO {
__brand = "DTO" as const;
}
class UserDTO extends DTO {
/* Commenting these out as they're not relevant to the question.
#IsDefined({message:"Username required"})
#Expose()
#Length(1,10, {message:"min 1 max 10"})
*/
username: string;
constructor(username: string) {
super();
this.username = username;
}
}
class BadDTO {
name: string = "";
}
function validateDTO(objToValidate: DTO, validateMissingProperties: boolean): string[] {
return [];
}
// Okay
validateDTO(new UserDTO("Joe"), true);
// Disallowed by the type system
validateDTO(new BadDTO(), false);
Playground link
Side note 2: In that example I added a constructor to UserDTO that initialized the username property. TypeScript has a shorthand for when you want to use a constructor paramter to initialize an instance property, this is functionally identical to the UserDTO in my example:
class UserDTO extends DTO {
/* Commenting these out as they're not relevant to the question.
#IsDefined({message:"Username required"})
#Expose()
#Length(1,10, {message:"min 1 max 10"})
*/
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− note no `username` declaration here
constructor(public username: string) {
// ^−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− note adding `public`
super();
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− note no code here to do the
// initialization; it's implicit in the `public` declaration above
}
}
Which you use is a matter of style.

In Haxe, how do you pass Enum values in functions, and then convert them to Strings within the function?

I can't seem to get this working, but I'd be surprised if it wasn't possible in Haxe.
I'm trying to pass a couple of Enum values defined in my game to a function, so that it can then concatenate them as String types and pass that to other functions.
Example:
// In a general Entity class:
public override function kill():Void {
messages.dispatchCombined(entityType, ListMessages.KILLED);
super.kill();
}
And in my Messages.hx class:
package common;
import msignal.Signal.Signal1;
/**
* A Message / Event class using Signals bound to String names.
* #author Pierre Chamberlain
*/
class Messages{
var _messages:MessagesDef;
public function new() {
_messages = new MessagesDef();
}
public function add(pType:String, pCallback:FuncDef) {
if (_messages[pType] == null) {
_messages[pType] = new Signal1<Dynamic>();
}
var signals = _messages[pType];
signals.add( pCallback );
}
public function dispatch(pType:String, pArg:Dynamic):Bool {
var signals = _messages[pType];
if (signals == null) return false;
signals.dispatch(pArg);
return true;
}
//Compiler doesn't like passing enums :(
public inline function addCombined(pSource:Enum, pEvent:Enum, pCallback:FuncDef) {
add( combine(pSource, pEvent), pCallback );
}
public inline function dispatchCombined(pSource:Enum, pEvent:Enum, pArg:Dynamic):Bool {
return dispatch( combine(pSource, pEvent), pArg);
}
//How can I just pass the enum "names" as strings?
static inline function combine(a:Enum, b:Enum):String {
return String(a) + ":" + String(b);
}
}
typedef MessagesDef = Map<String, Signal1<Dynamic>>;
typedef FuncDef = Dynamic->Void;
Note how addCombined, dispatchCombined and combine expect an "Enum" type, but in this case I'm not sure if Haxe actually expects the entire Enum "class" to be passed (ie: ListMessages instead of ListMessages.KILLED) or if a value should work. Anyways, compiler doesn't like it - so I'm assuming another special Type has to be used.
Is there another way to go about passing enums and resolving them to strings?
I think you need EnumValue as parameter type (if it is only for enum values), and use Std.String to convert to String values.
static inline function combine(a:EnumValue, b:EnumValue):String {
return Std.string(a) + ":" + Std.string(b);
}
Of course that can be written smaller using String interpolation:
static inline function combine(a:EnumValue, b:EnumValue):String {
return '$a:$b';
}
Of course that can be 'more dynamic' using type parameters:
static inline function combine<A, B>(a:A, b:B):String {
return '$a:$b';
}
There is totally no need to use Dynamic as suggested. If you use Dynamic, you basically turn off the type system.
live example:
http://try.haxe.org/#a8844
Use Dynamic instead of Enum or pass them as Strings right away since you can always convert to enum from String if you need it later.
Anyway pass the enum as enum:Dynamic and then call Std.string(enum);
EDIT: Using EnumValue is definitely better approach than Dynamic, I use Dynamic in these functions because I send more than just Enums there and I am not worried about type safety in that case.

Casting Dynamic to an other class

I would like to know if that's possible to cast a Dynamic to an other class (partially or totally)
For example, this code breaks :
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = cast(x, Test);
}
}
with the following message
Class cast error
However, my "Test" class has an "id" field like the dynamic object. (That's an example, my use case is more complexe than that ^^)
So, I don't understand how to get an object from my Dynamic one.
This isn't exactly casting a dynamic to a class instance but may accomplish the same thing:
create an empty instance of the class with Type.createEmptyInstance
set all of the fields from the Dynamic object on the new class instance using Reflect
Example:
import haxe.Json;
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = Json.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = Type.createEmptyInstance(Test);
for (field in Type.getInstanceFields(Test))
if (Reflect.hasField(x, field))
Reflect.setProperty(t, field, Reflect.getProperty(x, field));
trace(t.id);
}
}
You could use typedef
typedef Test = {
public var id: String;
}
class Main {
public static function main() {
var t:Test = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
}
}
Json.parse returns anonymous structure(implementation platform dependent), typed as Dynamic. There isn't a single chance to cast it to anything but Dynamic, unless Json.parse returns Int, Float or String, which some parsers permit, but which isn't actually permitted by JSON specification.
That is this way because, the operation of casting doesn't check what fields some object have. Operation of casting only checks if the object is an instance of class you are casting to. Obviously, anonymous structure can't be an instance of any class(inside haxe abstractions at least).
However, the right way to perform the thing you seem to be trying to perform is the way stated by #Ben Morris, in his answer.

AutoMapper: Map a source property on destination base

Here are two classes that I need to map, on the left side:
class HumanSrc {
public int IQ;
public AnimalSrc Animal;
}
class AnimalSrc {
public int Weight;
}
on the right side are the same objects, but composed using inheritance:
class HumanDst : AnimalDst {
public int IQ;
}
class AnimalDst {
public int Weight;
}
so the mapping I need is:
humanSrc.IQ -> humanDst.IQ
humanSrc.Animal.Weight -> humanDst.Weight;
I can easily do this mapping explicitly, but I have several classes that all derive from Animal, and Animal class is large, so I would prefer to map Animal once, and then have that included in every derived class mapping.
I looked at .Include<> method, but I do not think it supports this scenario.
Here is the essence of what I am looking for (pseudo-code):
// define animal mapping
var animalMap = Mapper.CreateMap<AnimalSrc, AnimalDst>().ForMember(dst=>dst.Weight, opt=>opt.MapFrom(src=>src.Weight);
// define human mapping
var humanMap = Mapper.CreateMap<HumanSrc, HumanDst>();
humanMap.ForMember(dst=>dst.IQ, opt=>opt.MapFrom(src=>src.IQ));
// this is what I want. Basically I want to say:
// "in addition to that, map this child property on the dst object as well"
humanMap.ForMember(dst=>dst, opt=>opt.MapFrom(src=>src.Entity));
As a workaround you can add BeforeMap with mapping base class. Probably it is not the best solution but at least it requires less mapping configuration:
humanMap.BeforeMap((src, dst) =>
{
Mapper.Map(src.Animal, (AnimalDst)dst);
});

How to dynamically create collections of derived objects?

This question may appear to have been answered before but I have been unable to find exactly what I need. Here is my situation:
// Base class
interface IAnimal {};
public abstract class Animal : IAnimal{}
// Derived classes
interface IDog {}
public class Dog : Animal, IDog { }
interface ICat { }
public class Cat : Animal, ICat { }
interface ITiger { }
public class Tiger : Animal, ITiger { }
interface ILion { }
public class Lion : Animal, ILion { }
// Collection Classes
interface IPets { }
public class Pets
{
IDog dog = new Dog();
ICat cat = new Cat();
}
interface ICircus { }
public class Circus
{
ITiger tiger = new Tiger();
ILion lion = new Lion();
}
I would like to create the collections at run time in an generic Event class by reading in a list animals from xml that would make up the collection. What would be the correct way to accomplish this?
Thanks in advance.
This is kind of an answer to my own question. Maybe this will help others.
I chose a very generic example to illustrate my situation because I have uses for this in many places in Windows Forms, XNA and Silverlight that are all very different.
When I used the Activator, I found out that it assumes the executing assembly. My method is in a library so I had to load a different assembly. Next I had to make sure that I had the right namespace. My base class is in a library and the derived classes are in another namespace so this will require refactoring to properly create the list.
Another problem I found was that the Activator assumes a constructor with no parameters. In my test case all my derived classes are XNA game components with a parameter of type Game.
Have to do some refactoring to test out the interfaces and how the game objects are to interact.
Will be back to this list when I have something further.
Does this sort of example help? (It's from some of my code I happened to have handy.) The key point here is the use of reflection in Activator.CreateInstance(...).
public static List<dynamic> LoadChildEntities(XElement entityElt)
{
var children = new List<dynamic>();
foreach(XElement childElt in entityElt.Elements("entity"))
{
// Look up the C# type of the child entity.
string childTypename = "MyNamespace." + Convert.ToString(childElt.Attribute("type").Value);
Type childType = Type.GetType(childTypename);
if(childType != null)
{
// Construct the child entity and add it to the list.
children.Add(Activator.CreateInstance(childType, childElt));
}
else
{
throw new InvalidOperationException("No such class: " + childTypename);
}
}
return children;
}
If you want a list of IAnimal instead, it wouldn't be too tricky to change.

Resources