Get parent class in Gobject - glib

I am new to GObject.I confused something about getting pointer to father of one class.For example ,
On Gobject Spec, we have a class:
struct _MamanBarClass {
GObjectClass parent;
/* class members */
};
what is the difference between :
MamanBarClass klass;
GObjectClass parent_class=G_OBJECT_CLASS(g_type_class_peek_parent (klass));
and
MamanBarClass klass;
GObjectClass g_object_class=G_OBJECT_CLASS(klass);
what is the difference between g_object_class and parent_class
One more question:
the difference between casting MamanBarClass(klass) and MAMANBARCLASS(klass)
thank you!

In GObject, any new type keeps a class struct in a register to keep runtime info, virtual methods and private class data.
The casting (G_OBJECT_CLASS(klass)) is used to retrieve the GObjectClass of klass while G_OBJECT_CLASS(g_type_class_peek_parent(klass)) returns the GObjectClass of the parent of klass. In your example, the former simply returns the GObjectClass struct of MamanBarClass while the latter returns the GObjectClass struct of the GObjectClass struct (the parent of MamanBarClass) found in the register. In practice:
klass = G_OBJECT_CLASS(maman_bar_class);
/* This will override MamanBar::dispose */
klass->dispose = my_dispose;
/* Now my_dispose will be called by g_object_dispose(object) when object is a MamanBar object */
klass = G_OBJECT_CLASS(g_type_class_peek_parent(klass));
/* This will override GObject::dispose */
klass->dispose = my_dispose
/* Now my_dispose will be called by g_object_dispose(object) when object is a GObject (the parent class of MamanBar) object */
(MamanBarClass *) klass and MAMAN_BAR_CLASS(klass) are equivalent, but the latter performs runtime type checking (emits a g_critical if klass is not a MamanBarClass *).

Related

How to access this in constructor? [duplicate]

In Dart, is there a difference in assigning values right away vs in constructor like in Java?
class Example {
int x = 3;
}
vs
class Example {
int x;
Example() {
x = 3;
}
}
I ask because when I was using Flutter and tried to assign a Function that uses setState to a variable, it was not possible with the former method but possible with the latter.
In your trivial case, it doesn't matter.
In general, you can initialize instance variables in a few ways:
Inline (field initializers)
class Example1 {
T x = value;
}
Advantages:
Direct, concise.
Member will be initialized in all constructors.
Can be used to initialize final or non-nullable members.
Member is initialized before invoking base class constructors, which is important when the base class constructor calls member functions that are overridden by the derived class.
Disadvantages:
Cannot depend on construction arguments.
Usually cannot depend on this since the initialization occurs before this becomes valid (i.e., cannot depend on other instance members). (An exception is if the member is initialized lazily by declaring it late. This requires the null-safety feature to be enabled.)
Initializer list
class Example2 {
T x;
Example2() : x = value;
}
Advantages:
Can be used to initialize final or non-nullable members.
Member is initialized before invoking base class constructors, which is important when the base class constructor calls member functions that are overridden by the derived class.
Can utilize construction arguments.
The initialized variable always refers to a member variable, never to a constructor parameter.
Disadvantages:
If the class has multiple constructors, initialization would need to be duplicated, or constructors should redirect to a common constructor.
Cannot depend on this since the initialization occurs before this becomes valid (i.e., cannot depend on other instance members).
Can initialize only members of the enclosing class. Because initializer lists are executed before invoking base class constructors, they cannot set base class members.
Constructor body
class Example3 {
T x;
Example3() {
x = value;
}
}
Advantages:
Can utilize construction arguments.
Can be used to perform more complicated initialization, such as cases where the member cannot be initialized via a single expression.
Can use this (i.e., can use other instance members).
Can be used to set base class members.
Disadvantages:
Cannot be used to initialize non-late final nor non-nullable members.
If the class has multiple constructors, initialization would need to be duplicated or initialization code would need to be refactored out (such as, but not limited to, redirecting to a common constructor).
Member is initialized after invoking base class constructors.
If the constructor has a parameter that shadows a member variable, it's easy to accidentally refer to the parameter instead of the member. (See https://github.com/dart-lang/linter/issues/2552 for details.)
There probably are some points I'm forgetting, but I think that should cover the main ones.
Direct, inline initialization occurs first, then initialization lists, then constructor bodies. Also see Difference between assigning the values in parameter list and initialiser list, which explains why this becomes valid only for the later stages of object initialization.
As an example where it matters where members are initialized:
class Base {
Base() {
doSomething();
}
void doSomething() {}
}
class DerivedEarly extends Base {
int? x;
DerivedEarly() : x = 42;
#override
void doSomething() => print(x);
}
class DerivedLate extends Base {
int? x;
DerivedLate() {
x = 42;
}
#override
void doSomething() => print(x);
}
void main() {
DerivedEarly(); // Prints: 42
DerivedLate(); // Prints: null
}

Is there a way to access a mixin's private variable in the class using the mixin?

In dart when creating a mixin, you can declare properties and methods like a class. When declaring a private property/method, it seems the inheriting class should also have access to this private member (see below for example).
Is there a way to access a mixin's private variable in the class using the mixin?
If it's not possible, how can I declare a member in the mixin object but make it private in the inheriting class's interface.
mixin.dart
mixin A {
String propertyOne = '1';
// This property is not accessible to any inheriting class.
int _privateProperty = 2;
}
class.dart
class B with A {
String get mixinString => propertyOne;
// This property is not accessible to the B class.
int get mixinInt => _privateProperty;
}
No. A property being library private means that you can only express its name inside the same library. In any other library, the identifier _privateProperty is a different name, one private to that other library.
If you cannot declare both mixin and class in the same library, and you definitely need access to the property, then you can do any number of things to allow that.
Make the property public and tell people not to use it except in subclasses. They still can if they want to.
Make the property public and mark it #protected, to have the analyzer tell people to not use it except in subclasses. They still can if they want to.
Keep the property private and provide a separate method to access it:
mixin A {
// This property is not accessible to any inheriting class.
int _privateProperty = 2;
static int getPrivateProperty(A a) => a._privateProperty;
static void setPrivateProperty(A a, int value) {
a._privateProperty = value;
}
}
Anyone can still get to the property if they really want to, but they need to know that
it comes from A.

Opaque Type with Class

A/c to Apple Doc,
A function or method with an opaque return type hides its return value’s type information. Instead of providing a concrete type as the function’s return type, the return value is described in terms of the protocols it supports
EDIT: Cutting the whole question short
/* PROTOCOLS */
protocol MyPros {}
/* STRUCT */
struct MyStruct {}
/* CLASSES */
class ClassA : MyPros {}
class ClassB : ClassA {}
class ClassC : ClassB {}
Now I using Opaque return type, 1. with struct 2. with class
/* FUNCTIONS */
func getOpaqueStruct() -> some MyStruct { // ERROR: An 'opaque' type must specify only 'Any', 'AnyObject', protocols, and/or a base class
return MyStruct()
}
func getOpaqueClass() -> some ClassC {
return ClassC()
}
getOpaqueStruct returns error which is understandable, if you check getOpaqueClass , getOpaqueClass also not returning protocols, and/or a base class so why class object able to return any class object in the inheritance chain. It also must be returns the baseclass i.e. classA or protocol i.e. MyPros.
ClassC can be in future be superclass of ClassD but base class of these chain is ClassA.
I think you are misunderstanding what the phrase "base class" in the error message means. It doesn't mean "a class that doesn't inherit from anything, and can have subclasses". It just means "a class that can have subclasses" or in other words, "a class that other classes can inherit from".
Why only limit the feature to classes that doesn't inherit from anything, when anything that could have subclasses can benefit from this feature.
Old answer (to revision 3 of the question):
You can't do some StructType because structs don't have subclasses. They whole point of opaque return types is to allow you to tell the caller that:
I'm returning a definite type, but you don't need to know what type this is. You just need to know it is a subclass of XXXClass/confomer of YYYProtocol.
No other types can inherit from structs, so if you have a method that is said to return some StructType, then it can only return StructType, nothing else. This defeats the purpose of opaque return types.
From the name of your method, writing:
func getPlanet() -> some Planet {
return Earth(name: "Earth", creatures: "Humans")
}
would make more sense in my opinion.
The caller knows that getPlanet will return a definite type, that is a conformer of Planet.

Initialize a final variable with "this" in Dart

I have a class like this:
class A extends B {
final Property<bool> property = Property<bool>(this);
}
class Property<T> {
Property(this.b);
final B b;
}
But I get an error on this saying:
Invalid reference to 'this' expression.
I believe I can't access this at that moment, probably because the object reference is not ready yet.
So I tried other forms of initializing that variable like:
class A extends B {
final Property<bool> property;
A() : property = Property<bool>(this);
}
But I get the same error.
The only thing that works is:
class A extends B {
Property<bool> property;
A() {
property = Property<bool>(this);
}
}
Which needs me to remove the final variable declaration, which is something I don't want to.
How can I initialize a final variable in Dart that needs a reference to the object itself?
You can't reference this in any initializers as this hasn't yet been initialized itself, so you won't be able to set Property<bool> property to be final.
If you're just trying to prevent modification of the value of property from outside the instance, you can use a private member and provide a getter to prevent modification. Given your example, that would look something like this:
class A extends B {
// Since there's no property setter, we've effectively disallowed
// outside modification of property.
Property<bool> get property => _property;
Property<bool> _property;
A() {
property = Property<bool>(this);
}
}

Dependency inject a generic struct without having to re-specify placeholder type or constraints

I'm trying to dependency inject a generic struct into a class, but I don't want to have to re-specify the generic's placeholder type again in the class as well. That gets out of hand because any class that uses this class will have to do the same, on and on.
For instance, this works:
struct SomeStruct<T : CustomStringConvertible> {
let data: T
}
class SomeClass {
let someStruct = SomeStruct(data: 1)
}
However, if I want to dependency inject the struct into the class, I get an error:
struct SomeStruct<T : CustomStringConvertible> {
let data: T
}
class SomeClass {
let someStruct: SomeStruct
// ^
// Reference to generic type 'SomeStruct' requires arguments in <...>
init(someStruct: SomeStruct) {
// ^
// Reference to generic type 'SomeStruct' requires arguments in <...>
self.someStruct = someStruct
}
}
So then I have to specify the placeholder type and type constraints again in the class:
struct SomeStruct<T : CustomStringConvertible> {
let data: T
}
class SomeClass<T : CustomStringConvertible> {
let someStruct: SomeStruct<T>
init(someStruct: SomeStruct<T>) {
self.someStruct = someStruct
}
}
Is there some way to get around the need to re-specify the placeholder type and constraints in the class? Why can't the class just know that SomeStruct holds data: CustomStringConvertible?
No, this is not possible. You're trying to describe a concept that would allow specify a concrete (class) type:
class SomeClass { ... }
but using a non-concrete type as a member
class SomeClass {
let someStruct: SomeStruct // <-- non-specified generic type, what placeholder should we use?
}
For any concrete types, their members must also be concrete
// OK
class SomeClass {
let someStruct: SomeStruct<Int>
}
whereas you could allow generic members if their types is tied to a generic typeholder of the owning type (SomeClass) itself
// OK (assuming there is no type constraint on the
// generic placeholder in the definition of SomeStruct)
class SomeClass<T> {
let someStruct: SomeStruct<T>
}
Finally, with regard to the "repeated" type constraints: if the generic placeholder for some given type, say SomeStruct<T> as in your question, is under some type constraint, then naturally (static typing) any typeholder "propagated" as generic type specifier in usages of the generic SomeStruct must be ensured to conform to the same constraints as those applied to the generic placeholder in SomeStruct. Hence, you cannot avoid specifying the same type constraints in the generic class SomeClass<T: ...> to which SomeStruct is used as a generically tied member.
struct SomeStruct<T : CustomStringConvertible> {
let data: T
}
class SomeClass<T> {
let someStruct: SomeStruct<T>
/* ^ this placeholder is not guaranteed to fulfil
the type constraints which are applied to the
generic typeholder of SomeStruct, hence the
illegality */
}
CustomStringConvertible is not a concrete type. The compiler can not infer what the base type (conforming to CustomStringConvertible) really is.
For this specific case, if the only capability SomeClass needs from someStruct is the ability to access data as a String, then you should simply convert your injected types (like someStruct) into strings first.

Resources