I have a GObject "A" which creates an instance of another GObject "B" in its constructor.
The "B" object needs to be passed several construction-only properties. Now when creating an instance of object "A" I want to allow passing values for these properties through the constructor of object "A" on to the constructor of object "B".
The only way I have found to do that was to create identical properties for object "A" and pass their values on to the constructor of "B". These properties would have no further meaning to "A" so this seems like a kludge.
Is there a better way to do what I want?
Have A inherit from B. Then A has all of B's properties automatically.
Don't use properties in A, but instead pass B's properties (or even better, an already-constructed B object) as parameters to A's constructor.
Delay construction of B until A can figure out how it nees to configure B. Add a private flag to A, b_initialized or something, that tells you whether A's internal pointer to B is valid.
Some more clarification on the second suggestion:
A's stuff is constructed in the a_init() function that is provided for by the G_DEFINE_TYPE() macro. But that's not how you get an instance of A. It's usual to write a function, which is part of the public interface of A, like this:
A *a_new()
{
return (A *)g_object_new(TYPE_A, NULL);
}
You can easily extend this to include other parameters:
A *a_new(int b_param_1, int b_param_2)
{
A *a = (A *)g_object_new(TYPE_A, NULL);
a->priv->b = b_new(b_param_1, b_param_2);
return a;
}
This has the disadvantage of leaving your A object in an invalid state (i.e., without a B) if you construct it using g_object_new, for example if you're trying to build it from a GtkBuilder file. If that's a problem, I still strongly suggest refactoring.
Use dependency injection, pass an already initialized object of type B to the constructor of A.
That way the client that is using your class can decide whether to pass in different kinds of Bs (if it makes sense you can even use an interface instead of a class as the B type, writing code against interfaces is generally better than writing code against implementations).
Deriving A from B only makes sense if it really is a specialization of it's parent class.
From the question it isn't clear if derivation makes sense, but it's an often overused method for composition.
Related
Is there a way (I'm sure there is out of runtime check...) to specify that a parameter or a variable in general conforms to multiple types? to avoid doing something such as
work (a_printer: PRINTER; a_scanner: SCANNER)
do
a_printer.print
a_scanner.scan
-- OR without second parameter
if attached {SCANNER} a_printer as l_scanner then
l_scanner.scan
else
throw RuntimeError
end
end
If feature work belongs to a class that may have formal generic parameters, it could be defined as taking one argument of the corresponding formal generic type:
class X [D -> {PRINTER, SCANNER}] feature
work (device: D)
do
device.scan
device.print
end
end
Then, at the caller site, one could make the call
x.work (multi_function_device)
where x has an appropriate type, e.g. X [MULTI_FUNCTION_PRINTER].
If work could also be declared and implemented as a class feature, the temporary variable could be avoided:
{X [like multi_function_device]}.work (multi_function_device)
If the auxiliary class X is not an option, the current version of the language provides no means to declare an argument as conforming to more than 1 type (e.g., work (d: {PRINTER, SCANNER})), so you would have to resort to preconditions like
work (p: PRINTER)
require
attached {SCANNER} p
do
check
from_precondition: attached {SCANNER} p as s
then
s.scan
end
p.print
end
I think that, if possible, you should use a common ancestor to your multiple types. If you cannot (if you are using library types), you can create descendant classes (MY_PRINTER inherit from PRINTER and DEVICE and MY_SCANNER inherit from SCANNER and DEVICE). Another way is to use ANY as the type, but it is not the best solution.
I fully understand that a System.Array is immutable.
Given that, why does it have an Add() method?
It does not appear in the output of Get-Member.
$a = #('now', 'then')
$a.Add('whatever')
Yes, I know this fails and I know why it fails. I am not asking for suggestions to use [System.Collections.ArrayList] or [System.Collections.Generic.List[object]].
[System.Array] implements [System.Collections.IList], and the latter has an .Add() method.
That Array implements IList, which is an interface that also covers resizable collections, may be surprising - it sounds like there are historical reasons for it[1]
.
In C#, this surprise is hard to stumble upon, because you need to explicitly cast to IList or use an IList-typed variable in order to even access the .Add() method.
By contrast, since version 3, PowerShell surfaces even a type's explicit interface implementations as direct members of a given type's instance. (Explicit interface implementations are those referencing the interface explicitly in their implementation, such as IList.Add() rather than just .Add(); explicit interface implementations are not a direct part of the implementing type's public interface, which is why C# requires a cast / interface-typed variable to access them).
As a byproduct of this design, in PowerShell the .Add() method can be called directly on System.Array instances, which makes it easier to stumble upon the problem, because you may not realize that you're invoking an interface method. In the case of an array, the IList.Add() implementation (rightfully) throws an exception stating that Collection was of a fixed size; the latter is an exception of type NotSupportedException, which is how types implementing an interface are expected to report non-support for parts of an interface.
What helps is that the Get-Member cmdlet and even just referencing a method without invoking it - simply by omitting () - allow you to inspect a method to determine whether it is native to the type or an interface implementation:
PS> (1, 2).Add # Inspect the definition of a sample array's .Add() method
OverloadDefinitions
-------------------
int IList.Add(System.Object value)
As you can see, the output reveals that the .Add() method belongs to the Ilist interface.
[1] Optional reading: Collection-related interfaces in .NET with respect to mutability
Disclaimer: This is not my area of expertise. If my explanation is incorrect / can stand improvement, do tell us.
The root of the hierarchy of collection-related interfaces is ICollection (non-generic, since v1) and ICollection<T> (generic, since v2).
(They in turn implement IEnumerable / IEnumerable<T>, whose only member is the .GetEnumerator() method.)
While the non-generic ICollection interface commendably makes no assumptions about a collection's mutability, its generic counterpart (ICollection<T>) unfortunately does - it includes methods for modifying the collection (the docs even state the interface's purpose as "to manipulate generic collections" (emphasis added)). In the non-generic v1 world, the same had happened, just one level below: the non-generic IList includes collection-modifying methods.
By including mutation methods in these interfaces, even read-only/fixed-size lists/collections (those whose number and sequence of elements cannot be changed, but their element values may) and fully immutable lists/collections (those that additionally don't allow changing their elements' values) were forced to implement the mutating methods, while indicating non-support for them with NotSupportedException exceptions.
While read-only collection implementations have existed since v1.1 (e.g, ReadOnlyCollectionBase), in terms of interfaces it wasn't until .NET v4.5 that IReadOnlyCollection<T> and IImmutableList<T> were introduced (with the latter, along with all types in the System.Collections.Immutable namespace, only available as a downloadable NuGet package).
However, since interfaces that derive from (implement) other interfaces can never exclude members, neither IReadOnlyCollection<T> nor IImmutableCollection<T> can derive from ICollection<T> and must therefore derive directly from the shared root of enumerables, IEnumerable<T>.
Similarly, more specialized interfaces such as IReadOnlyList<T> that implement IReadOnlyCollection<T> can therefore not implement IList<T> and ICollection<T>.
More fundamentally, starting with a clean slate would offer the following solution, which reverses the current logic:
Make the major collection interfaces mutation-agnostic, which means:
They should neither offer mutation methods,
nor should they make any guarantees with respect to immutability.
Create sub-interfaces that:
add members depending on the specific level of mutability.
make immutability guarantees, if needed.
Using the example of ICollection and IList, we'd get the following interface hierarchy:
IEnumerable<T> # has only a .GetEnumerator() method
ICollection<T> # adds a .Count property (only)
IResizableCollection<T> # adds .Add/Clear/Remove() methods
IList<T> # adds read-only indexed access
IListMutableElements<T> # adds writeable indexed access
IResizableList<T> # must also implement IResizableCollection<T>
IResizableListMutableElements<T> # adds writeable indexed access
IImmutableList<T> # guarantees immutability
Note: Only the salient methods/properties are mentioned in the comments above.
Note that these new ICollection<T> and IList<T> interfaces would offer no mutation methods (no .Add() methods, ..., no assignable indexing).
IImmutableList<T> would differ from IList<T> by guaranteeing full immutability (and, as currently, offer mutation-of-a-copy-only methods).
System.Array could then safely and fully implement IList<T>, without consumers of the interface having to worry about NotSupportedExceptions.
To "Add" to #mklement0's answer: [System.Array] implements [System.Collections.IList] which specifies an Add() method.
But to answer why have an Add() if it doesn't work? Well, we haven't looked at the other properties, i.e. IsFixedSize :
PS > $a = #('now', 'then')
PS > $a.IsFixedSize
True
So, a [System.Array] is just a [System.Collections.IList] that is a Fixed Size. When we look back at the Add() method, it explicitly defines that if the List is Read-Only or Fixed Size, throw NotSupportedException which it does.
I believe the essence is not, "Let's have a function that just throws an error message for no reason", or to expand on it, No other reason than to fulfill an Interface, but it actually is providing a warning that you are legitimately doing something that you shouldn't do.
It's the typical Interface ideas, you can have an IAnimal type, with an GetLeg() method. This method would be used 90% of all animals, which makes it a good reason for implementing into the base Interface, but would throw an error when you use it against a Snake object because you didn't first check the .HasFeet property first.
The Add() method is a really good method for a List Interface, because it is an essential method for Non-Readonly and Non-Fixed length lists. We are the ones being stupid by not checking that the list is not IsFixedSize before calling an Add() method that would not work. i.e. this falls into the category of $null checks before trying to use things.
This is a sort of followup to my previous question about nested registered C functions found here:
Trying to call a function in Lua with nested tables
The previous question gave me the answer to adding a nested function like this:
dog.beagle.fetch()
I also would like to have variables at that level like:
dog.beagle.name
dog.beagle.microchipID
I want this string and number to be allocated in C and accessible by Lua. So, in C code, the variables might be defined as:
int microchipIDNumber;
char dogname[500];
The C variables need to be updated by assignments in Lua and its value needs to be retrieved by Lua when it is on the right of the equal sign. I have tried the __index and __newindex metamethod concept but everything I try seems to break down when I have 2 dots in the Lua path to the variable. I know I am probably making it more complicated with the 2 dots, but it makes the organization much easier to read in the Lua code. I also need to get an event for the assignment because I need to spin up some hardware when the microchipIDNumber value changes. I assume I can do this through the __newindex while I am setting the value.
Any ideas on how you would code the metatables and methods to accomplish the nesting? Could it be because my previous function declarations are confusing Lua?
The colon operator (:) in Lua is used only for functions. Consider the following example:
meta = {}
meta["__index"] = function(n,m) print(n) print(m) return m end
object = {}
setmetatable(object,meta)
print(object.foo)
The index function will simply print the two arguments it is passed and return the second one (which we will also print, because just doing object.foo is a syntax error). The output is going to be table: 0x153e6d0 foo foo with new lines. So __index gets the object in which we're looking up the variable and it's name. Now, if we replace object.foo with object:foo we get this:
input:5: function arguments expected near ')'
This is the because : in object:foo is syntactic sugar for object.foo(object), so Lua expects that you will provide arguments for a function call. If we did provide arguments (object:foo("bar")) we get this:
table: 0x222b3b0
foo
input:5: attempt to call method 'foo' (a string value)
So our __index function still gets called, but it is not passed the argument - Lua simply attemps to call the return value. So don't use : for members.
With that out of the way, let's look at how you can sync variables between Lua and C. This is actually quite involved and there are different ways to do it. One solution would be to use a combination of __index and __newindex. If you have a beagle structure in C, I'd recommend making these C functions and pushing them into the metatable of a Lua table as C-closures with a pointer to your C struct as an upvalue. Look at this for some info on lua_pushcclosure and this on closures in Lua in general.
If you don't have a single structure you can reference, it gets a lot more complicated, since you'll have to somehow store pairs variableName-variableLocation on the C side and know what type each is. You could maintain such a list in the actual Lua table, so dog.beagle would be a map of variable name to one or two something's. There a couple of options for this 'something'. First - one light user data (ie - a C pointer), but then you'll have the issue of figuring out what that is pointing to, so that you know what Lua type to push in for __index and what to pop out for __newindex . The other option is to push two functions/closures. You can make a C function for each type you'll have to handle (number, string, table, etc) and push the appropriate one for each variable, or make a uber-closure that takes a parameter what type it's being given and then just vary the up-values you push it with. In this case the __index and __newindex functions will simply lookup the appropriate function for a given variable name and call it, so it would be probably easiest to implement it in Lua.
In the case of two functions your dog.beagle might look something like this (not actual Lua syntax):
dog.beagle = {
__metatable = {
__index = function(table,key)
local getFunc = rawget(table,key).get
return getFunc(table,key)
end
__newindex = function(table,key,value)
local setFunc = rawget(table,key).set
setFunc(table,key,value)
end
}
"color" = {
"set" = *C function for setting color or closure with an upvalue to tell it's given a color*,
"get" = *C function for getting color or closure with an upvalue to tell it to return a color*
}
}
Notes about the above: 1.Don't set an object's __metatable field directly - it's used to hide the real metatable. Use setmetatable(object,metatable). 2. Notice the usage of rawget. We need it because otherwise trying to get a field of the object from within __index would be an infinite recursion. 3. You'll have to do a bit more error checking in the event rawget(table,key) returns nil, or if what it returns does not have get/set members.
I have a struct:
struct Order
{
public string orderNumber;
public string orderDetail;
}
I then assign some values in Form1 and try to pass them by reference (ref) to Form2:
(Form1)
Order order = new Order();
order.orderNumber = "1234";
order.orderDetail = "Widgets";
Form2 frm2 = new Form2(ref order);
Is it possible to store the values in Form2 so that when Form2 is completed processing the values it will return the updated struct values to Form1?
In this scenario there would be a button that would close the form after validating the data.
One pattern that's sometimes useful is to define a class something like:
class Holder<T> {public T value;}
Such a class makes it possible to pass and mutate value types with code that requires reference types. Using such an approach, a routine which accepted a structure by reference and was supposed to pop up a modal dialog and fill in the structure from it, could create a Holder<thatStructType>, pass that to the form, and then copy the data from that Holder back to the passed-in reference. While in your particular scenario, it may be better to have the data-holding thing simply be a class, structures have the advantage that one can know that no outstanding references to them exist; if a routine declares a structure and passes it by reference to some outside code, then once that code returns the values in that structure won't change unless or until the routine writes them itself or passes the structure by reference to some other code. By contrast, if a routine exposes a class reference to outside code, there's no telling what that code may do with it.
Incidentally, the Holder class is also useful in a number of other scenarios. For example, if one has a Dictionary<String, Holder<Integer>> myDict, one may use Threading.Interlocked.Increment(myDict(myKey).Value)) to perform a thread-safe increment of the indicated item, much more efficiently than would be possible with a Dictionary<String, Integer>.
What I think you're asking is if Form2 can store a reference to the order structure that was passed in the constructor. The answer is no. If you want to store references, use a reference type (a class).
If a class A is in composition relationship with class B , does it mean that the specific instance of B got via A should only be modifiable through class A not to break the data encapsulation of class A? Or, does composition imply only life-time bind, not the data encapsulation ?
class A
{
B itsB;
B* getB() {return &itsB);
}
void AnotherClass::anyOperation()
{
itsA->getB()->function(); // is this legal ?
}
Composition does not strictly specify the rules concerning whether a composed object should be allowed to be modified outside the composing class or not.
Encapsulation has to do with controlling access to the members defined in a class to outside world. In general ,fields of a class should not be directly accessible by outside code , if this tenet is followed , then the question of allowing it to be modifeid by outside code does not arise. Encapsulation and composition are not related in principle , so in your example , the fact that B is a composed into A itself does not dictate the rule that itsB should not be modifiable outside A.
However , you should think in terms of 1. Who owns the object itsB ? 2. Is it thread-safe to allow it to be modified outside A ? Is it breaking encapsulation ?
If B has public setter functions, the only way in C++ to ensure that nobody retrieves A's B through getB() and changes its value is for getB() to return a constant reference. If it returned a constant pointer, that just ensures that you don't change the pointer; you can still change the values inside the B that the pointer points to.
To mention my problem with different words:
The class A has mB and mC members , where A and B, A and C are in composition relationships.
B and C classes are in association relationship.
What would you say, if I want to link specific instance "mB" to specific instance "mC" (of class A), allowing them to communicate between themselves.
Would it mean to break the encapsulation provided by A for mB and mC ?