I actually make use of directory~setmethod in a few places, notably to make
a directory case agnostic like this:
.directory~new~~setmethod('UNKNOWN',"if self~hasIndex(upper(arg(1))) then
return self[upper(arg(1))] ; else return .nil")

I know of only two ways to test whether an object instance has certain
capabilities.
ISA or HASMETHOD.

In a universe where subclasses removed their parents capabilities by
over-riding methods with um, 'unMethods' then neither of these tests would
be universally valid.

The advantage of Rony's suggestion is that it is easy then to replace
instances of DIRECTORY in ones code with instances of STRINGTABLE without
having to check for calls to setMethod or unsetmethod.  The workaround is
to check for calls to setmethod or unsetmethod before making the change, or
even undo the change when you see the error "a STRINGTABLE does not
understand message SETMETHOD".

IMHO although there would be benefits to making this change, the cost here
far outweigh them, so I am a -1 on this one.

Jon



On 22 November 2015 at 15:00, Moritz Hoffmann <[email protected]> wrote:

> I agree that it would be a bad idea to replace various .Directory
> instances by .StringTable. Remembering B. Meyer in his programming language
> class: Preconditions can only be weakened by inheritance, postconditions
> can be strengthened. An parameter type requirement is comparable to a
> precondition, so the same holds here. [1]
> It is well known that certain real-world relationships are hard or
> impossible to model using object-oriented design, but the bird example can
> be solved. Image the hierarchy is actually a relationship model with many
> dimensions. Then, bird ancestry and birds able to fly are two orthogonal
> dimensions which cannot be expressed in one hierarchy. Multiple inheritance
> is an attempt to solve the problem, but it comes with its own ambiguities.
>
> Moritz
>
> [1] https://en.wikipedia.org/wiki/Liskov_substitution_principle
>
> On Sun, Nov 22, 2015 at 3:34 PM Rick McGuire <[email protected]>
> wrote:
>
>>
>>
>> On Sunday, November 22, 2015, Rony G. Flatscher <[email protected]>
>> wrote:
>>
>>>
>>>
>>> On 20.11.2015 15:42, Gil Barmwater wrote:
>>> > On 11/18/2015 1:24 PM, Rony G. Flatscher wrote: >> Experimenting a bit
>>> further with 5.0alpha looking into the new >> .StringTable which should
>>> supercede/replace the .Directory class as >> it is faster than .Directory
>>> (by removing the feature to have >> methods generate a return value upon
>>> lookup). >> >> Running the following experiment: >> >>
>>> F:\download\Rexx\ooRexx\alpha500\work\bin_small>rexx rexxtry.rex >>
>>> REXX-ooRexx_5.0.0(MT)_32-bit 6.05 4 Nov 2015 rexxtry.rex lets you >>
>>> interactively try REXX statements. Each string is executed when you >> hit
>>> Enter. Enter 'call tell' for a description of the features. Go >> on - try
>>> a few...            Enter 'exit' to end. say .stringtable >> The
>>> StringTable class ........................................... >>
>>> rexxtry.rex on WindowsNT say .stringtable~isa(.directory) 0 >>
>>> ........................................... rexxtry.rex on >> WindowsNT do
>>> i over .stringtable~superclasses;say i;end The Object >> class The
>>> MapCollection class >> ...........................................
>>> rexxtry.rex on >> WindowsNT do i over .directory~superclasses;say i;end The
>>> Object >> class The MapCollection class >>
>>> ........................................... rexxtry.rex on >> WindowsNT say
>>> .local .local~class The Local Directory The Directory >> class
>>> ........................................... rexxtry.rex on >> WindowsNT >>
>>> >> It would be nice, if .local and .environment and other Directory >>
>>> objects in existing code could get replaced by StringTable >> instances to
>>> benefit from its better performance. >> >> In order to allow .StringTable
>>> as a drop-in replacement for >> .Directory it would only be necessary to
>>> make .StringTable a >> subclass of .Directory (the speciality of
>>> .StringTable would be to >> remove a particular lookup feature, if I
>>> understood the >> explanations by Rick correctly). This way existing code
>>> would be >> able to get gradually enhanced by replacing .Directory objects
>>> by >> .StringTable objects (even in native code that might test whether >>
>>> an object is a .Directory). >> >> Would that make sense? >> >> ---rony > A
>>> recent post by Ruurd about the "Decorator" design pattern got me to > do
>>> some reading about OO design patterns and principles.  While I'm > still
>>> working my way through it all, I did find an interesting > principle that I
>>> believe applies here.  It is call the LSP (Liskov > Substitution Principle)
>>> and it states that "subtypes must be > substitutable for their base
>>> types".  The way I understand it, > creating a subclass that removes
>>> functionality of its superclass is > not good design practice.
>>> This depends very much on the context, purpose: consider e.g. a class
>>> tree of birds which are of course able to fly (have a method fly
>>> implemented or accessible via inheritance). Then, when you hit a new class
>>> of birds that does not fly (like an ostrich) you are confronted with class
>>> of birds that has as one speciality (justifying an own class) that it lost
>>> the ability to fly.
>>>
>>> There are at least two solutions to this problem: you arrange, if you
>>> can, the entire class tree and make the ostrich class the superclass of all
>>> other birds, where one of its subclasses adds the method "fly", such that
>>> that class' subclasses gain the ability to fly. In most real world cases
>>> changing a design of an existing class hierarchy as fundamentally as
>>> suggested with this approach is probably impractical.
>>>
>>> The other solution is that you subclass the bird class that resembles
>>> ostrichs the most and make sure that the ostrich's method "fly" gets
>>> removed by implementing the fly method and raising a syntax condition
>>> indicating that this method got removed. This way you make sure that
>>> ostrichs don't fly, but that programs which mistakingly invoke the fly
>>> method on them get a syntax condition that makes it aware of the error.
>>>
>>> > So your suggestion to have .StringTable be a subclass of .Directory >
>>> would violate the LSP.  However, reversing that relationship - > .Directory
>>> as a subclass of .StringTable - would be OK.
>>> LSP is about semantics, which depend on the context.
>>>
>>> Looked up the methods of .Directory and .StringTable, and indeed the
>>> methods setMethod and unsetMethod are not implemented in .StringTable.
>>> Making .StringTable a subclass of .Directory would cause it to inherit
>>> those two methods, so no runtime error would occur. However, if these two
>>> methods get excercised by any program, then that program would assume that
>>> the unknown method would invoke it and return the value like in the case of
>>> .Directory, which is undesirable, if such an invocation gets unnoticed.
>>>
>>> To resolve this issue it is sufficient (in the case one wishes to make
>>> .StringTable a subclass of .Directory) to implement the two methods
>>> setMethod and unsetMethod in .StringTable and generate a syntax error
>>> indicating that the method got removed in the .StringTable class. This
>>> avoids the above mentioned situation (and the one LSP tries to inhibit)
>>> that an inconsistency gets introduced that goes unnoticed. Thiw would allow
>>> .StringTable to become a drop in replacement for .Directory, if programmers
>>> wish to do so.
>>>
>>> As Rick mentions in his RFE that led to the implementation of
>>> .StringTable (cf.
>>> <https://sourceforge.net/p/oorexx/feature-requests/615>
>>> <https://sourceforge.net/p/oorexx/feature-requests/615>) it is very
>>> rarely the case that this particular functionality (that a method gets set
>>> with the .Directory) is exploited. But the need to check whether a method
>>> lookup needs to take place slows down access.
>>>
>>> The resulting class .StringTable serves as a (faster look-up) .Directory
>>> replacement. As such it would be desirable to become able to replace the
>>> usage of .Directory with .StringTable in one owns programs where one is
>>> also able to determine that the setMethod and unsetMethod messages have
>>> never been exploited.
>>>
>>> > Now, that does not allow for testing for isA(.Directory) to work with
>>> > .StringTable objects w/o modification but the code needs to be > changed
>>> to create the object as a .StringTable anyway so I don't see > that as a
>>> big drawback.
>>> That would be a rather big problem as isA(.Directory) is probably used
>>> in quite a few programs that have a need to assure that a received argument
>>> is of type .directory. In the native C++ interface listings there is an
>>> explicit IsDirectory() API to ease testing for it. One would need to
>>> replace all programs (Rexx or native) and replace isA(.Directory) with
>>> isA(.StringTable).
>>>
>>> Given that .Directory has been so important to ooRexx that it has been
>>> employed quite strongly, and given, that the .Directory features setMethod
>>> and unsetMethod have almost never been employed (I know of no ooRexx
>>> program, except test programs), it is very unlikely (but not impossible)
>>> that replacing .Directory with .StringTable in client code would cause any
>>> problems.
>>>
>>> > > On your other suggestion - to change .local and .environment to >
>>> instances of .StringTable - I'm afraid I don't agree.  While most >
>>> programs, I would guess, only use the methods of those .Directory > objects
>>> that are also methods of .StringTable, there may be cases > that depend on
>>> the "other" methods which would then break if this > change were made.
>>> You are right w.r.t. .local and .environment. If someone exploits the
>>> setMethod and unsetMethod feature and has applied it to these two
>>> environment directories, which are always available to Rexx programs, then
>>> those programs would stop working all of a sudden, if they get replaced by
>>> .StringTable instances.
>>>
>>> In fact the environment object already uses setmethod so this really is
>> not possible.
>>
>> Form a good oo practice standpoint, this is a bad idea.  It is
>> inappropriate for a subclass to remove capability.  This would make a
>> isa(.directory) test meaningless since you would need additional tests to
>> determine that the object could fulfill all of the expectations of a
>> directory.  a better solution would be to use a time machine and go back
>> and add stringtable and make directory a subclass of that.  I think that
>> solution is not likely, since we would not even be having this conversation
>> if it was 😄
>>
>> Rick
>>
>>
>>
>>>
>>>
>>> ---rony
>>>
>>>
>>>
>>
>>
>>
>>
>>
>> ------------------------------------------------------------------------------
>> _______________________________________________
>> Oorexx-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/oorexx-devel
>>
>
>
> ------------------------------------------------------------------------------
>
> _______________________________________________
> Oorexx-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/oorexx-devel
>
>
------------------------------------------------------------------------------
_______________________________________________
Oorexx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to