@jim said:
@jessejames said:
I noticed when i do obj.methods, and obj.private_methods, there is a lot of pollution in there. Names that obviously don't belong to that obj.
I wouldn't call it pollution. You're seeing all the methods that the object has. Some of them are inherited, some are class methods, others are instance methods. I suspect what you expected to see were only the instance methods of a class.
This is VERY important! For understanding Ruby,... but more so.. how the Sketchup Ruby API (and standard Pure-Ruby extensions (such as 'sketchup.rb' [as the best example,]) can be incorrectly implemented.
Ruby scripts... (if you don't tell them specifically what namespace to run in,) will run in (the global constant namespace,) TOPLEVEL_BINDING. (A Binding class object, is 'sort-of' an execution directive to a namespace.)
(1) TOPLEVEL_BINDING is preset to Object (uppercase.)
(2) Everything in Ruby is an object (lowercase,) meaning it is either an Object class, or a subclass (at some level of descendancy,) of Object class. [You may think of the lowercase word 'class' as 'type' if you come from a language where 'type' is more understandable. But recent revisions to Ruby are attempting to remove the word 'type' in favor of 'class.' Keep in mind that there is in Ruby a class Class, which is subclass of class Module, which is subclass of class Object.]
(3) The Sketchup Ruby Console operates in TOPLEVEL_BINDING. (Open the console and type: self <ENTERkey> , what do you see?
(4) Any script loaded runs in TOPLEVEL_BINDING.
(5) This means that most objects defined in TOPLEVEL_BINDING are in fact then defined WITHIN class Object. So if you define a method (without wrapping it with a Class or Module namespace, it is defined as a method of class Object. (Take a look at the 'sketchup.rb' script in the Tools folder and note the names of the methods defined there.)
(6) As every object in Ruby is a subclass of Object, every object will inherit (in some way,) those objects defined within class Object, including methods, constants, etc. IF you have incorrectly defined them there.
(7) The methods within the 'sketchup.rb' script were intended (for the most part,) to extend developer's use of the classes Module and Class. BUT they were not wrapped within the proper namespace(s) in the script, and so get defined as methods of Object, and so become inherited by ALL classes, such as the Numeric classes, the Sketchup::Entity subclasses, the Geom::subclasses, etc. where they will NEVER be used.
Open a new model, draw something simple a cube, select a Sketchup::Face object. Switch to the console, type (all 1 command):
**Sketchup.active_model.selection[0].private_methods(true).sort.join("\n")**
Look at the list, you will see that the Face object has inherited as private methods (which you will never call from outside the object,) all those methods defined in 'sketchup.rb'!
What kind of drain of memory will this have when you get to a model that has tens of thousands of Entities it it?
"How do you fix this?"
(a) ANSWER: 'sketchup.rb' MUST DIE! The methods within NEED to be moved (defined as an extension,) to the proper %(#BF0000)Module where they should have been added in the first place:
to module Sketchup:
-
file_loaded* file_loaded?* require_allto module UI:
-
add_separator_to_menu* inputbox (really a patch that needs to be made part of UI.inputbox.)
(b) Edit any script you use, that does not wrap it's code in a module namespace, especially method definitions with a module wrapper. Don't use any rbs (scrambled ruby) that you cannot wrap. (Contact the author and ask they wrap their code.)
(c) If you can.. use the load method with the wrap parameter set true, for menu command scripts, etc. when editing many many plugins is not an option. (The wrap argument for load will wrap the script in an anonymous namespace, and protect the global namespace from corruption.)
(d) Ask the Google Sketchup Team to fix the Sketchup::load method to expose the wrap argument, so we can specify wrap=true for rbs scripts. For some unknown reason, they defeated, or just didn't pass the 2nd argument (wrap) on to the aliased standard load, when they overrode it to handle rbs decrypting.
_