I'm currently testing some simple AngelScript stuff, and noticed something I find a bit strange when it comes to how objects are initialized from classes.
Let's say I define a class like this:
class MyClass {
int i;
MyClass(int i) {
this.i = i;
}
}
I can create an object of this class by doing this:
MyClass obj = MyClass(5);
However it seems I can also create an object by doing this:
MyClass obj;
The problem here is that obj.i becomes a default value as it is undefined.
Additionally, adding a default constructor to my class and a print function call in each one reveals that when I do MyClass obj = MyClass(5); BOTH constructors are called, not just the one with the matching parameter. This seems risky to me, as it could initialize a lot of properties unnecessarily for this "ghost" instance.
I can avoid this double-initialization by using a handle, but this seems more like a work-around rather than a solution:
MyClass# obj = MyClass(5);
So my question sums up to:
Can I require a specific constructor to be called?
Can I prevent a default constructor from running?
What's the proper way to deal with required parameters when creating objects?
Mind that this is purely in the AngelScript script language, completely separate from the C++ code of the host application. The host is from 2010 and is not open-source, and my knowledge of their implementation is very limited, so if the issue lies there, I can't change it.
In order to declare class and send the value you choose to constructor try:
MyClass obj(5);
To prevent using default constructor create it and use:
.
MyClass()
{
abort("Trying to create uninitialized object of type that require init parameters");
}
or
{
exit(1);
}
or
{
assert(1>2,"Trying to create uninitialized object of type that require init parameters");
}
or
{
engine.Exit();
}
in case that any of those is working in you environment.
declaring the constructor as private seems not to work in AS, unlike other languages.
Related
Im trying to load my model in my controller and tried this:
return Post::getAll();
got the error Non-static method Post::getAll() should not be called statically, assuming $this from incompatible context
The function in the model looks like this:
public function getAll()
{
return $posts = $this->all()->take(2)->get();
}
What's the correct way to load the model in a controller and then return it's contents?
You defined your method as non-static and you are trying to invoke it as static. That said...
1.if you want to invoke a static method, you should use the :: and define your method as static.
// Defining a static method in a Foo class.
public static function getAll() { /* code */ }
// Invoking that static method
Foo::getAll();
2.otherwise, if you want to invoke an instance method you should instance your class, use ->.
// Defining a non-static method in a Foo class.
public function getAll() { /* code */ }
// Invoking that non-static method.
$foo = new Foo();
$foo->getAll();
Note: In Laravel, almost all Eloquent methods return an instance of your model, allowing you to chain methods as shown below:
$foos = Foo::all()->take(10)->get();
In that code we are statically calling the all method via Facade. After that, all other methods are being called as instance methods.
Why not try adding Scope? Scope is a very good feature of Eloquent.
class User extends Eloquent {
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
public function scopeWomen($query)
{
return $query->whereGender('W');
}
}
$users = User::popular()->women()->orderBy('created_at')->get();
Eloquent #scopes in Laravel Docs
TL;DR. You can get around this by expressing your queries as MyModel::query()->find(10); instead of MyModel::find(10);.
To the best of my knowledge, starting PhpStorm 2017.2 code inspection fails for methods such as MyModel::where(), MyModel::find(), etc (check this thread), and this could get quite annoying.
One (elegant) way to get around this is to explicitly call ::query() wherever it makes sense to. This will let you benefit from free auto-completion and a nice formatting/indentating for your queries.
Examples
BAD
Snippet where inspection complains about static method calls
// static call complaint
$myModel = MyModel::find(10);
// another poorly formatted query with code inspection complaints
$myFilteredModels = MyModel::where('is_foo', true)
->where('is_bar', false)
->get();
GOOD
Well formatted code with no complaints
// no complaint
$myModel = MyModel::query()->find(10);
// a nicely formatted and indented query with no complaints
$myFilteredModels = MyModel::query()
->where('is_foo', true)
->where('is_bar', false)
->get();
Just in case this helps someone, I was getting this error because I completely missed the stated fact that the scope prefix must not be used when calling a local scope. So if you defined a local scope in your model like this:
public function scopeRecentFirst($query)
{
return $query->orderBy('updated_at', 'desc');
}
You should call it like:
$CurrentUsers = \App\Models\Users::recentFirst()->get();
Note that the prefix scope is not present in the call.
Solution to the original question
You called a non-static method statically. To make a public function static in the model, would look like this:
public static function {
}
In General:
Post::get()
In this particular instance:
Post::take(2)->get()
One thing to be careful of, when defining relationships and scope, that I had an issue with that caused a 'non-static method should not be called statically' error is when they are named the same, for example:
public function category(){
return $this->belongsTo('App\Category');
}
public function scopeCategory(){
return $query->where('category', 1);
}
When I do the following, I get the non-static error:
Event::category()->get();
The issue, is that Laravel is using my relationship method called category, rather than my category scope (scopeCategory). This can be resolved by renaming the scope or the relationship. I chose to rename the relationship:
public function cat(){
return $this->belongsTo('App\Category', 'category_id');
}
Please observe that I defined the foreign key (category_id) because otherwise Laravel would have looked for cat_id instead, and it wouldn't have found it, as I had defined it as category_id in the database.
You can give like this
public static function getAll()
{
return $posts = $this->all()->take(2)->get();
}
And when you call statically inside your controller function also..
I've literally just arrived at the answer in my case.
I'm creating a system that has implemented a create method, so I was getting this actual error because I was accessing the overridden version not the one from Eloquent.
Hope that help?
Check if you do not have declared the method getAll() in the model. That causes the controller to think that you are calling a non-static method.
For use the syntax like return Post::getAll(); you should have a magic function __callStatic in your class where handle all static calls:
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
The newtypes tutorial shows you how to inherit from a base python class. Can you inherit from your own python class? Something like this?
PyObject *mod = PyImport_AddModule("foomod");
PyObject *o = PyObject_GetAttrString(mod, "BaseClass");
PyTypeObject *t = o->ob_type;
FooType.tp_base = t;
if (PyType_Ready(&FooType ) < 0) return NULL;
though you need to define your struct with the base class as the first member per the documentation so it sounds like this is not possible? ie how would I setup the Foo struct?
typedef struct {
PyListObject list;
int state;
} SubListObject;
What I'm really trying to do is subclass _UnixSelectorEventLoop and it seems like my only solution is to define a python class that derives from my C class and from _UnixSelectorEventLoop with my C class listed first so that it can override methods in the other base class.
I think you're basically right on your assessment:
it seems like my only solution is to define a python class that derives from my C class and from _UnixSelectorEventLoop with my C class listed first so that it can override methods in the other base class.
You can't define a class that inherits from a Python class because it'd need to start with a C struct of basically arbitrary size.
There's a couple of other options that you might like to consider:
You could create a class the manual way by calling PyType_Type. See this useful answer on a question about multiple inheritance which is another sort of inheritance that the C API struggles with. This probably limits you too much, since you can't have C attributes, but you can have C functions.
You could do "inheritance by composition" - i.e. have you _UnixSelectorEventLoop as part of the object, then forward __getattr__ and __setattr__ to it in the event of unknown attributes. It's probably easier to see what I mean with Python code (which is simply but tediously transformed into C API code)
class YourClass:
def __init__(self,...):
self.state = 0
self._usel = _UnixSelectorEventLoop()
def __getattr__(self, name):
return getattr(self._usel, 'name')
def __setattr__(self, name, value):
if name in self.__dict__:
object.__setattr__(self, name, value)
else:
setattr(self._usel, name, value)
# maybe __hasattr__ and __delattr__ too?
I'm hoping to avoid having to write this C API code myself, but the slots are tp_getattro and tp_setattro. Note that __getattr__ will need to be more comprehensive in the C version, since it acts closer to the __getattribute__ in Python. The flipside is that isinstance and issubclass will fail, which may or may not be an issue for you.
Is there any way for a static property in a Powershell class to contain a generic dictionary? Without the initialisation syntax that exists in C#, I haven't found a way to do it.
enum Environment
{
Production
QA
Dev
}
class Config
{
# How to get this populated?
static [System.Collections.Generic.Dictionary[Environment, hashtable]] $EnvData
}
Potential workarounds:
Add-Type and a C# class
A GetEnvData() method
Is there a better way I haven't thought of?
Just like in C#, you can use the static constructor (which is what initializers are syntactic sugar for, anyway):
class Config
{
static [System.Collections.Generic.Dictionary[Environment, hashtable]] $EnvData
static Config() {
$d = New-Object ([System.Collections.Generic.Dictionary[Environment, hashtable]])
$d["Production"] = #{Setting="Foo"}
[Config]::EnvData = $d
}
}
The use of a local is not strictly required, but I sleep better knowing the initialization is atomic.
You can also use an initializer ($EnvData = ...) but that's a little tricky in this case, since creating a generic Dictionary in one statement is, well, awkward, and the class syntax doesn't like it if you get complicated (pipes, nested function calls). You could still, if you so wanted, split off initialization into a separate hidden static function and call that for initialization (... $EnvData = [Config]::initialEnvData()), which may be more readable than one big constructor if you've got many conceptually independent properties.
I'm working on finishing up my server for my first iPhone application, and I want to implement a simple little feature.
I would like to run a function (perhaps method as well), if another function returns a certain value after a certain waiting period. Fairly simple concept.... right?
Here's my basic foundation.
template <typename T,class TYP>
struct funcpar{
T (*function)(TYP);
TYP parameter;
funcpar(T (*func)(TYP),TYP param);
funcpar& operator=(const funcpar& fp);
};
The goal here is to be able to call funcpar::function(funcpar::parameter) to run the stored function and parameter, and not have to worry about anything else...
When I attempted to use a void* parameter instead of the template, I couldn't copy the memory as an object (because I didn't know what the end object was going to be, or the beginning for that matter) and when I tried multiple timers, every single object's parameter would change to the new parameter passed to the new timer... With the previous struct I have a
question:
Is it possible to make an all-inclusive pointer to this type of object inside a method of a class? Can I templatize a method, and not the whole class? Would it work exactly like a function template?
I have a managing class that holds a vector of these "jobs" and takes care of everything fairly well. I just don't know how to use a templatized function with the struct, or how to utilize templates on a single method in a class..
I'm also utilizing this in my custom simple threadpool, and that's working fairly well, and has the same problems...
I have another question:
Can I possibly store a function with a parameter before it's run? Something like toRun = dontrunmeyet(withThisParameter);? Is my struct even necessary?
Am I going about this whole thing incorrectly?
If this is overly ambiguous, I can set you up with my whole code for context
In order to create a class method that takes a template parameter, yes, it would work almost exactly like a function template. For example:
class A
{
public:
template<typename T>
void my_function(const T& value) { }
};
int main()
{
A test;
test.my_function(5);
return 0;
}
Secondly, for your structure, you can actually turn that into a functor-object that by overloading operator(), lets you call the structure as-if it were a function rather than having to actually call the specific function pointer members inside the structure. For instance, your structure could be re-written to look like this:
#include <iostream>
template <class ReturnType, class ParameterType>
class funcpar
{
private:
ReturnType (*function)(ParameterType);
ParameterType parameter;
public:
funcpar(ReturnType (*func)(ParameterType),ParameterType param):
function(func), parameter(param) {}
funcpar& operator=(const funcpar& fp);
//operator() overloaded to be a function that takes no arguments
//and returns type ReturnType
ReturnType operator() ()
{
return function(parameter);
}
};
int sample_func(int value)
{
return value + 1;
}
int main()
{
funcpar<int, int> test_functor(sample_func, 5);
//you can call any instance of funcpar just like a normal function
std::cout << test_functor() << std::endl;
return 0;
}
BTW, you do need the functor object (or your structure, etc.) in order to bind a dynamic parameter to a function before the function is called in C/C++ ... you can't "store" a parameter with an actual function. Binding a parameter to a function is actually called a closure, and in C/C++, creating a closure requires a structure/class or some type of associated data-structure you can use to bind a function with a specific parameter stored in memory that is used only for a specific instance of that function call.
I'm wondering if someone can explain the difference between the functions below. They are both static, but require different signature syntaxes. I'm wondering how these are handled at runtime, and why you would use one over the other?
+ (int) returnInt:(NSString *)myString1 withString2:(NSString *)myString2
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
vs.
static int returnInt(NSString *myString1, NSString *myString2)
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
Thanks!
Unlike in (say) C++, where static member functions are just ordinary functions in the class' namespace, Objective-C has proper class methods.
Since classes are objects, calling a class method is really like calling an instance method on the class. The main consequences of this are:
1) Calling a class method incurs a slight (although generally inconsequential) overhead, since method calls are resolved at runtime.
2) Class methods have an implicit 'self' argument, just like instance methods. In their case, 'self' is a pointer to the class object.
3) Class methods are inherited by subclasses.
together, 2 and 3 mean that you can do stuff like this with a class method:
+ (id) instance
{
return [[[self alloc] init] autorelease];
}
then create a new class that inherits the method and returns a new instance of itself, rather than the superclass.
I believe that marking an ordinary c function static will just make it unavailable to files other than the one it's defined in. You'd generally do this if you wanted to make a helper function that is only relevant to one class and you wanted to avoid polluting the global namespace.