Safely extend sketchup class
-
I'd like to extend the functionality of Geom::Point3d by adding new methods. But of course I'm worried about conflicting with someone else who has already added the same method. I've read here before that extending a sketchup base class is discouraged for that reason. Is there a safe way to do this? Can I keep my own methods in my own module, or my own namespace somehow?
If I create my own subclass of Point3d, then my new methods won't work on objects that I get from examining existing geometry. Say I'm looking at an Edge, find one of the vertices, and then want to do something with vertex.position. It's type is not of my subclass, so I can't call my special methods.
-
It is tempting to extend a base class with a quick new method because it can be done relatively easily... however, as you say it might conflict with others methods with the same name.
Let's look at a hypothetical example...
You want to test to see if a point is between two other points, so you extend the Geom::3dpoint class with a new method 'point.between?(point1,point2)
' which returns true or false, after doing some calculations using 'self' as the point that's being tested and the two other points passed to it.
However, in your own tool's module or class you could have simply made an internal method which is then used in the form 'self.point_between?(p0,p1,p2)
' where the method is passed the point to be tested (p0) and the other two points that it might be between (p1 and p2)... and the code used in your safely wrapped code can be virtually identical to the extended base-class version code, except that whenever 'self' would have been used you will substitute 'p0'. So often it's possible easily to side step the angst of tinkering with the base classes... I'm sure there are ways of safely extending it... but remember to KISS...
The simpler that base-class extension is the less excuse you have for doing it!
[But we have all been tempted to do it! ] -
To make a point TIG missed making:
@tig said:
Let's look at a hypothetical example...
You want to test to see if a point is between two other points, so you extend the Geom::3dpoint class with a new method 'point.between?(point1,point2)
' ...... the
between?()
method is a standard Ruby method, that comes from theComparable
mixin module. If the class in question, to be extended, is the type of class that needs to be compared between other instances of itself, or similar 'compatible' objects... then it's likely thatComparable
has already been mixed in (or will be in the future as we've asked for this on several classes.)So.. you would be overriding a base method, and could possibly cause havoc.
-
Well, I wouldn't overwrite an existing method. And what I have in mind is a little more complicated than .between? Mine would be Point3d.same_side_of_plane?(Point3d, plane). But I could just write points_on_same_side_of_plane?(Point3d, Point3d, plane), which is safer, if somewhat less elegant.
-
Remember that
Geom::Point3d
class is compatible withArray
which the Sketchup API extends with many extra methods.
see: http://code.google.com/apis/sketchup/docs/ourdoc/array.htmlIt may be safer and easier to create a subclass of
Array
.
When making a newPoint3d
object, thenew()
constructor can take anArray
argument, although the API docs don't clearly say that. -
So lets say you had an Array subclass called
MyPoint
. SinceArray
'snew
method can take anotherArray
object as it's arg, and makes a copy..... and your subclass inherits that... you can do this:
pt = MyPoint.new( someEdge.end.position.to_a )
-
@daiku said:
I'd like to extend the functionality of
Geom::Point3d
by adding new methods.OK.. it's time to comment on this topic, in a general sense.
Methods added to the API, need to be of use to everyone (not just one developer, nor just one single plugin.) As TIG showed, if you need a method for a specific plugin, and it's possible using existing methods to write a private helper method within your own module, then that is the first course to take.
The API is a system of modules, classes and methods. Like any system, the larger it gets, the more costly it is to document and maintain. For that main reason, it takes a very good argument for us to convince the GSU development team to add any new methods to the API.
We have been experimenting with a pure Ruby 'extended' API library. But it needs to be just that, a public library, that is released, and version controlled via a project group. Single developers releasing extensions to the API modules and classes, to suit themselves, is a no-no.
-
@dan rathbun said:
Remember that
Geom::Point3d
class is compatible withArray
which the Sketchup API extends with many extra methods.
see: http://code.google.com/apis/sketchup/docs/ourdoc/array.htmlIt may be safer and easier to create a subclass of
Array
.
When making a newPoint3d
object, thenew()
constructor can take anArray
argument, although the API docs don't clearly say that.That's a good advice for 3d points.
-
For your "point and plane test" it's easy enough to make your own tool's method without messing on with any base-classes...
def point_test(point, plane, cond=false) ### 'point' is the point to test, ### 'plane' is the plane to test and ### 'cond' allows you to return true/false IF point is ON the plane. ### NOW add your code here that see if the 'point' is on, in front or behind the 'plane' ### returns 'behind' as 'true' or 'false', with a tweak for the 'cond' setting if behind return false else return true end#if end#def
Then in other code within your toolset use
self.point_test(point, plane, true)
where 'point' is to be tested for its relationship with 'plane', and here the third argument 'true' says to take 'point' as being 'in front' even if it's ON the plane too... [you would use no third argument or 'false' if point ON plane is to be 'invalid']
Advertisement