Inherit from Sketchup Classes
-
I tried to make a custom Vector class inheriting from GEOM::Vector3D. The inheritance in it self was no problem, no error messages, no warnings or anything.
class MyClass < Geom;;Vector3d end
This works fine
Then i modified my custom MyClass initialize method to accept 4 instead of 3 arguments.
class MyClass < Geom;;Vector3d def initialize(x,y,z,weight) @weight = weight super(x,y,z) end end myvector = MyClass.new(1,2,3,0.3)
This will throw an error message saying i have to many arguments (4 for 3). It seems like MyClass doesnt overwrite the Vector3d.initialize method. If im changing my initialize method back to 3 arguments:
class MyClass < Geom;;Vector3d def initialize(x,y,z) puts "Im here" @weight = weight super(x,y,z) end end myvector = MyClass.new(1,2,3,0.3)
Doesn't write anything to the console. It like my custom initialize method is never accessed. But myvector.class == MyClass???
Anyone? Is this because Vector3d is a reflection of a c++ / c class? (is it?). Are Sketchup denying me my rights as a rubyist to do whatever i want? Is it in ruby possible to lock the arrity of a method? Am i forgetting something?
Regards
Pierre -
I've found this troublesome as well.
It might be that initialize isn't used by C objects. ( Maybe .new must be overridden? )
I have in some experiments just extended the objects with a mix-in module. Though I suppose that won't solve the problem of custom initializion... -
A Vector3d is by its very nature an array-like object with three values.
Vectors do have .length; is this not what you want and called 'weight' ?
I can't see how you might use 'weight' as a 4th argument anyway ?
Couldn't you just use len=v.length and v.length=12.3 methods that already exist? -
@TIG: In this case a vector is to be considered a force in my Ivy plugin. Early in de development I did some experimenting with changing the and updating the ivy after it was actualy created (by selecting the ivy group and changing multipliers, or selecting a branch in the ivy and changing multipliers on just that one). I therefor needed to store the individual vectors and its multiplier. This became very complex very fast, very overkill and i guess its not even nessecary to store the multiplier anyway. But the problem regarding inheritance stuck and is still bugging me (even its not a problem at the moment).
-
The 'force' of a vector is its 'length' ?
This is already available to be read from the vector or can also be set... -
yes and no. The force is a vector multiplied by a weight multiplier. I wanted to store the user set multiplier with the vector so that i could manipulate the multiplier later
-
You misconstrue - you can vary a vector's length without affecting its direction so making it longer gives it more 'force' but its direction is unchanged, normalizing it later gives it 'unit length'...
-
@pierreden said:
I tried to make a custom Vector class inheriting from Geom::Vector3d. The inheritance in it self was no problem, no error messages, no warnings or anything.
... Is this because Vector3d is a reflection of a c++ / c class? (is it?). Are Sketchup denying me my rights as a rubyist to do whatever i want?
I also had tried to subclass a C++ Sketchup class (UI::Toolbar in my case.) I think the fault lies with the Google C++/C side code, in that the number of arguments to the new() constructor method is not setup to accept any number of args. This is normally wrong for Ruby. When we create classes we should always be sure that new() can take any number of arguments, and always pass the entire argument list into the initialize method in the instance object after it is created.
So the ArgumentError exception is really being raised by Ruby during the call to new().Now, that would make you believe, that you need to overrride the new() constructor method in your subclass, and call super() within the overridden method, with only the base set of arguments.
I tried that, it doesn't work either.Neither does aliasing the original constructor method under a different name, and creating a fresh new() method, that calls the aliased one.
In the end.. I just wrote a custom wrapper base class (being as a default, a direct subclass of Object,) that in it's own initialize() method, created a instance reference, to a new UI::Toolbar object.)
Then I wrote wrapper methods that mimic all the Toolbar instance methods, and added custom methods of my own, that add functionality.Now.. there are good reasons, in some cases for Google to have limited (or prevented,) the subclassing of some classes, such as all those subclasses of Sketchup::Drawingelement. Otherwise the application would not know how to draw the objects. (A Pandora's Box scenario.)
Likely they just did it all one way for all their classes, and never envisioned us wanting to do all the crazy things we can do with Ruby. -
Based on your description it seems unclear as to why you'd want to use inheritance here when the goal is to simply store the weights associated with the vector. I can envision either a class with a .vector and .weight attribute and some supporting methods. Here are some examples of what I think would be cleaner implementations of your idea.
class MyClass attr_accessor ;weight def initialize(x,y,z,weight) @vector = Geom;;Vector3d.new(x,y,z) @weight = weight end def vector return @vector.transform(@weight) end end
This would cleanly differentiate between the underlying Vector3d and the weight you want to store and allows you to update the weight while encapsulating the scaling behavior in the .vector method. The only downside of this approach is that occasionally you'll have to type my_class.vector.method instead of my_class.method but it avoids the semantic muddling of the underlying vector defined by the x,y,z values provided to initialize and the weighted version of it.
-
I ran some simple tests in the webdialog Ruby Code Editor. It seems that creating a sub-class has a number of issues (although some may be specific to the webdialog code editor):
- In my example, none of the code created within the sub-class was executed
- You can extend the parent class and create new methods, but any new methods in the sub-class are not recognized.
how about doing the following (taken from an example found here: http://railstips.org/blog/archives/2009/08/07/patterns-are-not-scary-method-missing-proxy/)
class MyVector attr_reader ;v attr_accessor ;wt def initialize(x,y,z,wt) @v = Geom;;Vector3d.new(x,y,z) end private def method_missing(method, *args, &block) args = args.collect{|a| a.v if a.is_a? MyVector} @v.send(method, *args, &block) end end
This takes care of the following scenario:
myVector1.angle_between myVector2
Although, this doesn't take care of what happens if you send a MyVector instance to another Sketchup class, such as
t = Geom::Transformation.new(myVector1) --> returns error
--
Karen -
@tig said:
You misconstrue - you can vary a vector's length without affecting its direction so making it longer gives it more 'force' but its direction is unchanged, normalizing it later gives it 'unit length'...
@cleverbeans said:
Based on your description it seems unclear as to why you'd want to use inheritance here when the goal is to simply store the weights associated with the vector. I can envision either a class with a .vector and .weight attribute and some supporting methods. Here are some examples of what I think would be cleaner implementations of your idea.
> class MyClass > attr_accessor ;weight > def initialize(x,y,z,weight) > @vector = Geom;;Vector3d.new(x,y,z) > @weight = weight > end > def vector > return @vector.transform(@weight) > end > end >
Yes. you are perfectly right. I'm sort of new to the concept of vectors, and it have taken me a while to get comfortable with the concept. My question wasn't about this particular example, bur rather the concept of inhereting from Sketchup classes. I would love to be able to make my own My::Point3d class with additional methods, and still be able to use My::Point3d together with Geom::Point3d without errors.
Peace
Pierre -
@pierreden said:
I would love to be able to make my own My::Point3d class with additional methods, and still be able to use My::Point3d together with Geom::Point3d without errors.
That is possible though - I've done that. It's just the new and initialize method that can't be modified by the looks of it.
-
@pierreden said:
I would love to be able to make my own My::Point3d class with additional methods, and still be able to use My::Point3d together with Geom::Point3d without errors.
The other option is to extend an instance of a Point3d...
module YourPoint3d attr_accessor ;your_var1, ;your_var2 def your_def1 end def your_def2 end end p = Geom;;Point3d.new p.extend YourPoint3d p.your_var1 = 20
This gives your particular Point3d additional methods and attributes without messing with the Point3d class at all.
--
Karen
Advertisement