Passing pointer/reference to object - qml

I'm writting a simple game where I've Player object and Enemy object. I want Enemy to pursue Player but I've no idea what is the right way of passing current Player's position to Enemy.
Natively I'm a C++ dev so I was naturally thinking of passing Player (probably as an interface) to Enemy but I cannot find any clue about such approach in QML.
How should I do it then?

Well, the best way would be using property bindings like hyde has already pointed out.
// Enemy.qml
Item {
property int targetX
property int targetY
// more code
}
// Player.qml
Item {
property int currentPosX
property int currentPosY
}
// Main.qml
Enemy {
id: enemy
targetX: player.currentPosX
targetY: player.currentPosY
}
Player {
id: player
// Some calculation for the current x and y position
}
Another approach would be to pass the Player component to the Enemy component. But than you have a little bit coupling. This is maybe the C++ thinking you have pointed out.
// Enemy.qml
Item {
id: enemy
property Item myPlayer
Component.onCompleted: {
console.log(enemy.myPlayer.currentPosX +
" | " +
enemy.myPlayer.currentPosY)
}
}
// Player.qml
Item {
property int currentPosX
property int currentPosY
}
// Main.qml
Enemy {
id: enemy
myPlayer: player
}
Player {
id: player
// Some calculation for the current x and y position
}

Ad mentioned here:
JavaScript expressions allow QML code to contain application logic.
Moreover:
QML offers a highly readable, declarative, JSON-like syntax with support for imperative JavaScript expressions combined with dynamic property bindings.
Because of that, you have not the notion of pointer in the QML environment, unless you push your logic under the hood, writing it in C++.
Anyway, almost everything in JavaScript is passed by reference (that's an acceptable simplification valid for your case, there are also some exceptions like primitive values and immutable objects).
Because of that, you can simply let your instance of A refers to an instance of B, either by passing it in the constructor or setting it by means of a setter or whatever (there is a plenty of alternative solutions indeed).
Keep in mind that there is no explicit support for interfaces neither in JavaScript nor in QML, so you cannot rely on them, even if you can simulate them (it isn't worth it from my point if view).
How to solve your specific problem?
Well, it depends on your actual code and software architecture, so I cannot say that, I'm sorry. I hope one of the hints above is of any help for you.

Related

kotlin get static type of a class property

I'm trying to get the type of some class properties in order to strongly typing my Kotlin Code.
In typescript, we can do this (stupid examplebut this is to explain)
class Test {
private _prop:string
constructor(val:Test["_prop"]){
this._prop = val
}
public get prop():Test["_prop"] { return this._prop}
}
const t:Test["_prop"] = "fdds"
The benefit here is that if I need to chnange the type of "_prop", no need to refactor the whole code, as the type is find thanks to Test["_prop"].
Is there a way to do this in Kotlin ?
I've seen reflection functions in Kotlin, but can't get what I want
Kotlin code :
class Test(val prop:Int) {
fun ppr() {
println(prop)
}
fun getProp():Int {
return prop
}
}
fun main() {
println("Hello, world!!!")
var t:Test = Test(4)
t.ppr()
var a:Int = t.getProp() // how to change :Int by "return type of func Test.prop
}
What you're trying to do is the opposite of strong typing. The point of a strong-typed system is that you're defining exactly what things are, and the system requires you to interact with those things correctly, and prevents you from doing things those types don't support
You're working with specific types and defined type hierarchies, and the way you can interact them is strongly enforced. It's possible to go outside the type system, e.g. with unchecked casts, or by reflection (which can get close to throwing the whole thing out completely) - but that's losing the benefits of strong typing, the guarantees and assistance it can provide, and makes errors a lot more likely
Basically if you want to change the type, you're supposed to refactor it. That lets the system handle it all for you systematically, and it will point out any problems that change might introduce, so you can resolve and handle them. This is another benefit of a strongly typed system - it can help you in this way
If you want to stay within the type system, but just want to update a type and avoid creating changes in a bunch of files, then #Sweeper's typealias approach will work - kinda abstracting a type definition away to one place (and you can give it a more meaningful name that doesn't reflect the specific type it happens to be right now). But if you meaningfully change what that underlying type is, your code will probably have to handle it anyway, unless you're just doing a common call on it like toString().
I might have got what you're asking for wrong, but I wanted to point this stuff out just in case, since you were talking about reflection and all!
You can't do it exactly like that in Kotlin, but you can declare a type alias, which sort of achieves the same result - enabling you to change the type of multiple things by editing only one place.
typealias PropType = Int
class Test(val prop: PropType) {
fun prop(): PropType {
return prop
}
}
To change the type of both, just change the typealias PropType = Int line.
However, note that you don't actually need to do this if you just want to write a getter. You don't need to explicitly write getters if all it does is just returning the property's value. If you want to do something extra in the getter, you can do:
class Test(prop: Int) {
val prop = prop
get() {
// do something extra in the getter
println("getting prop!")
return field // return the underlying field
}
}
The getter will be called whenever you access Test.prop, and again, you only need to change one place to change the type of the property.

Swift class properties not initialized when constructed by Objective C code

I'm attempting to create a class in Swift 3 to implement a Cordova plugin. I have this building and running, but the application crashes whenever any properties of the class are accessed. I've tried two ways of initializing the class:
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players = [UUID:DSFPlayerHandler] ();
...
}
and
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler];
override init () {
players = [:];
}
...
}
However, when my players property is used, the result is a EXC_BAD_ACCESS exception, with an address that looks like a null pointer dereference.
The object is being created by Objective C code, which is a language I have no familiarity with at all, but I think this is the line that creates it:
obj = [[NSClassFromString(className)alloc] initWithWebViewEngine:_webViewEngine];
The CDVPlugin class contains a comment stating that initWithWebViewEngine should not be overridden (and indeed I do not seem to be able to override this method, because while it is declared in the CDVPlugin.m file, it isn't mentioned in CDVPlugin.h, so the Swift compiler doesn't seem to know about it), but rather initialization code should be placed in a method called pluginInitialize instead. However, if I do that I get a compiler error ("Class DSFMediaCentre has no initializers").
Furthermore, if I put my init() method back in and set it to call pluginInitialize(), like this:
override init () {
super.init(); // necessary otherwise next line is an error
pluginInitialize();
}
override func pluginInitialize() {
players = [:];
}
the error then changes to "Property 'self.players' not initialized at super.init call".
How do I make this class initialize correctly?
You have a mismatch between the strict initialization system required by the language and the procedure used by the framework you're working with.
Swift demands that a) properties be initialized as part of object construction, and b) that construction be chained to the type's supertype. But the CDVPlugin type is doing the construction on your behalf; you don't have the ability to customize it. (This makes more sense in ObjC, because it doesn't have the same compile-time restrictions as Swift.)
The situation is similar to unpacking an object from a nib file. In that case too, because it's the nib loading system that's constructing your object, you don't have the ability to customize the initializer. Your type will always be constructed by init(coder:). In a certain sense, your initialization point moves further down, to awakeFromNib(), and among other things, that forces outlets to other objects in the archive to be declared as optional, usually implicitly unwrapped.
The same solution should avail you here. You should consider pluginInitialize() to be your initialization point. The language then requires that properties be optional, since they are not filled at its initialization point. Therefore, make the property an IUO:
#objc(DSFMediaCentre)
class DSFMediaCentre : CDVPlugin
{
var players :[UUID:DSFPlayerHandler]!
override func pluginInitialize() {
players = [:];
}
}
and all should be well.
The other solution is to use lazy keyword
lazy var players :[UUID:DSFPlayerHandler] = [:]
So, you don't need to initialize players in initializer but still make sure players always non-nulable

Cannot cast pointer field while can cast same pointer defined within method in managed classes

I have unmanaged object of WtfClass.
class WtfClass { };
And I also have managed class which uses pointer to this object.
ref class MyClass //works fine if you remove "ref"
{
public:
void MyMethod();
void WtfMethod(void * pVoid);
WtfClass *pWtfStruct;
};
void MyClass::MyMethod()
{
/*WtfClass* pWtfStruct; //if you uncomment this it will compile even with ref*/
WtfMethod((int*)(&pWtfStruct)); //(!!!invalid type conversion here)
}
void MyClass::WtfMethod(void *pVoid)
{}
I can't cast WtfClass* pointer from field, but can easily cast the same pointer defined within MyMethod(). If make MyClass unmanaged it works in any case.
It's better to look at screenshots:
https://ibin.co/2iOcN1ooaC7A.png [using ref-bad.png]
https://ibin.co/2iOcYtP84H0e.png [using ref-good.png]
ibin.co/2iOcjCCc2gQe.png [without ref.png] (sorry not enough reputation to paste more than 2 links)
Of course I can have workaround like this, but I'd like to understand why this happening:
void MyClass::MyMethod()
{
WtfClass* pWorkAround = pWtfStruct; //not required in this case
WtfMethod((void*)(&pWorkAround));
}
OK, so to summarize, without the duplicate field & local variable names:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
}
};
Side question: &fieldWtfPtr is of type WtfClass**, a double pointer. Did you mean to cast that to a int**, also a double pointer? Or perhaps did you want to take fieldWtfPtr as a WtfClass* single pointer and cast that to a int* single pointer?
Here's why you're getting the error: MyClass is a managed object. The garbage compiler is allowed to move it around at any point, without telling you. So, it's location in memory can change at any point. So when you try to take the address of a class field, it's not valid because the address of that field can change at any point!
Why the other things make it work:
Local variables are stored on the stack, and the stack doesn't get moved around by the garbage collector, so it is valid to take the address of a local variable.
If you remove the ref, then MyClass is no longer a managed object, so the garbage collector won't move it around, so now the addresses of its fields won't change willy-nilly.
For this case, the easiest fix would be to make use of a local temporary variable.
void foo()
{
WtfClass* localCopyWtfPtr = this->fieldWtfPtr;
WtfMethod((int*)(&localCopyWtfPtr)); // Works
// If WtfMethod changed the data, write it back.
this->fieldWtfPtr = localCopyWtfPtr;
}
When I tried to recreate this, the compiler generated the following error:
error C2440: 'type cast' : cannot convert from 'cli::interior_ptr<CWtfClass*>' to 'LPVOID *'
I think what is going on here is some magic that allows managed classes to have unmanaged members. The MSDN documentation for cli::interior_ptr describes what's going on - basically this is used to allow for the managed object to change its memory address in the managed heap, which would cause problems when native pointers come in to play.
The reason that assigning the member to a variable first works is most likely because it has an implicit conversion to the template parameter, but since it is a managed type the compiler won't allow you to get the address of the variable (since the garbage collector can move it around in memory as needed).
The workaround in your question is probably the best way to fix this compiler error.
David answered why this happens and suggested a workaround for your case.
I'll just post a different solution here: You can pin your managed object to tell the GC not to move it around. The most lightweight way to do that is through pin_ptr (the GC won't even know you pinned something unless it stumbles upon your code in the middle of a collection). As long as it stays in scope, the managed object will be pinned and won't move. It's best if you avoid pinning for too long, but this lets you get a pointer to a chunk of managed memory which is guaranteed not to move - it's helpful when you want to avoid copying things around.
Here's how to do it:
pin_ptr<WtfClass*> pin(&pWtfStruct);
WtfMethod(pin);
pin acts just like a WtfClass**.
Regarding side question of David Yaw.
I faced with this problem while used some WINAPI functions.
IAudioEndpointVolume* pWtfVolume = NULL;
pDevice->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pWtfVolume);
pWtfVolume->SetMute(BST_CHECKED, pGuidMyContext);
And it's working only if I pass &pWtfVolume. Ironically you can pass argument without "&", just pFieldVolume and compiler will say OKAY, but interface IAudioEndpointVolume will not work.
Look at this:
ref class MyClass
{
WtfClass* fieldWtfPtr;
void foo()
{
WtfClass* localvarWtfPtr;
WtfMethod((int*)(&fieldWtfPtr)); // Error
WtfMethod((int*)(&localvarWtfPtr)); // Works
WtfMethod((int*)(fieldWtfPtr)); // Compiles!!!
}
};

Chain up to 'Gtk.Box.new' not supported

I'm new to Vala and so far I think it's pretty cool but I'm having trouble understanding inheritance. I read here that I should use base() to call the parents constructor. Alright, cool, seems understandable but It din't work for me. I kept getting the error on the title. Here is my snippet to show:
public class MyBox : Gtk.Box {
public MyBox(Gtk.Orientation orientation, int spacing) {
// I have to this
this.set_orientation(orientation);
this.set_spacing(spacing);
// I want to do this:
base(orientation, spacing);
//workaround is this:
Object(orientation: orientation, spacing: spacing);
}
}
Please help me understand why Object(....) works but not base(...)
Shouldn't it be the same thing?
This is due to implementation of the C code. When Vala generates a constructor, it generates two C functions a _new function that allocates memory and calls the _construct and a _construct function that initialises the object. When you case the base constructor using base(), it needs a matching _construct function to call. Not all the classes written in C have this; in the VAPI file, you will find has_construct_function = false for some constructors. If this is the case, no chain-up can be done. The base GObject can set properties from arguments, so this becomes the only way to set defaults in the base class.

Reducing the number of arguments to a constructor

I am reading "Clean Code" and having trouble figuring out how to keep some of my functions (usually constructors) to their MAXIMUM of 3 parameters.
Often my objects need an awful lot of information to work - am I supposed to make a small constructor and then use mutator functions to give them all of the information? This doesn't seem any better than just using a big constructor.
As an example, I have a "MovablePatch" class. It lets the user drag a square around in a window. It needs a several parameters, including Radius, Color, Renderer, InitialPosition, and Visibility. Currently I collect all of these from my GUI and then call:
MovablePatch(int radius, Renderer* renderer, Color color, Position initial, bool visibility)
These are only some of the things that I need in this class. Can anyone suggest how else I might package this information to pass to the constructor? I don't see any obvious "break it into smaller classes" appearing here.
You could have
MovablePatch(Renderer* renderer, CircleAppearance circleAppearance)
where CircleAppearance gathers the other info.
However, clean code and other books that generalize about what good code should look like, are aiming for 80 percent of the code out there. Your code seems to be "closer to the metal" than the typical LoB (Line of Business) variety. As such, you may run into places where certain coding ideals are not applicable.
The most important part is that you're thinking about it and trying to keep things nice and tidy! :)
Do not take maxims like "thou shalt not have more than 3 parameters in thy constructors" at face value. If you have the slightest chance of making an object immutable, make it; and if it being immutable means that it is going to have a constructor with 50 parameters, so be it; go for it; don't even think about it twice.
Even if the object is going to be mutable, still, you should pass its constructor as many parameters as necessary so that immediately upon construction it will be in a valid and meaningful state. In my book, it is absolutely impermissible to have to know which are the magic mutator methods that have to be called (sometimes even in the right order) before any other methods can be invoked, under penalty of segfault.
That having been said, if you would really like to reduce the number of parameters to a constructor, or to any function, simply pass this method an interface that it can invoke to get from it the stuff it needs in order to work.
Some of the things you are passing in could be abstracted into a larger construct. For example, visibility, color, and radius, could make sense to be placed into an object that you define. Then, an instance of this class, call it ColoredCircle, could be passed into the constructor of MovablePatch. A ColoredCircle doesn't care where it is or what renderer it is using, but a MovablePatch does.
My main point, is that from an OO perspective, radius isn't really an integer, it's a radius. You want to avoid these long constructor lists because it is daunting to understand the context of these things. If you collect them into a larger class, kind of like how you already have with Color and Position, you can have fewer parameters passed in and make it easier to understand.
The Named Parameter Idiom is useful here. In your case, you might have
class PatchBuilder
{
public:
PatchBuilder() { }
PatchBuilder& radius(int r) { _radius = r; return *this; }
PatchBuilder& renderer(Renderer* r) { _renderer = r; return *this; }
PatchBuilder& color(const Color& c) { _color = c; return *this; }
PatchBuilder& initial(const Position& p) { _position = p; return *this; }
PatchBuilder& visibility(bool v) { _visibility = v; return *this; }
private:
friend class MovablePatch;
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
class MovablePatch
{
public:
MovablePatch( const PatchBuilder& b ) :
_radius( b._radius );
_renderer( b._renderer );
_color( b._color );
_position( b._position );
_visibility( b._visibility );
{
}
private:
int _radius;
Renderer* _renderer;
Color _color;
Position _position;
bool _visibility;
};
then you use it like so
int
main()
{
MovablePatch foo = PatchBuilder().
radius( 1.3 ).
renderer( asdf ).
color( asdf ).
position( asdf ).
visibility( true )
;
}
overly simplified, but I think it gets the point across. If certain parameters are required they can be included in the PatchBuilder constructor:
class PatchBuilder
{
public:
PatchBuilder(const Foo& required) : _foo(required) { }
...
};
Obviously this pattern degenerates into the original problem if all arguments are required, in which case the named parameter idiom isn't applicable. The point being, this isn't a one size fits all solution, and as Adam describes in the comment below there are additional costs and some overhead with doing so.
One good option is to use a Builder pattern, where each "setter" method returns the own instance, and you can chain the methods as you need.
In your case, you will get a new MovablePatchBuilder class.
The approach is very useful and you can find it in many different frameworks and languages.
Refer here to see some examples.