Jump to content

[Ask LAVA] Must Override exists; could Must Implement?


Recommended Posts

When subclassing, methods can be defined as Dynamic Dispatch, allowing implementations to override the parent. These implementations must have the same ConPane interface as the parent.

 

Further, the parent can (awesomely) declare "Must Override" per Dynamic Dispatch method, a contractual requirement of the subclass to implement the method. We're cool so far -- this is just a definition of how things work.

 

Here's where things get tricky: it's *so nice* to have that "Must Override" flag, yet you wish that implementations had a different ConPane than the parent method. Clearly, Dynamic Dispatch would be the incorrect choice, yet it hurts to give up "Must Override".

 

So what do you think: could there exist a concept of "Must Implement"? It's like "Must Override", yet does not require the subclasses implementation to adhere to a ConPane interface.

 

These Implemented methods act like a static method of the the class, only callable by the class and its descendants (this is not like Dynamic Dispatch, since a broken wire would result from wiring a Parent object to an Implemented method). The parent simply requires implementation -- the existence of a method -- without defining the interface.

 

Do other languages have this concept? Are there design patterns that address this need? Or is this desire for "Must Implement" indicative of poor OO design choices?

Link to comment

Hmm,

 

It sounds like you want the parent to have a partial abstract.  (that would be C# lingo, where partial means the definition of the implementation of the parent is incomplete, and abstract means it must be overridden; furthermore I've never done this in C# so I'm not even sure if its legal)  You'd can (or cannot) complete the parent implementation to match your (now known) override of the abstract implementation, but once you do that you'll have the same interface for all children of that parent (which is what I think you're trying to avoid)

 

ANYWAY

 

In labview, if I wanted to do this, I'd probably use something very similar to the Actor framework where the interface for all methods is itself a class (i.e. the message type)  It basically creates an additional abstraction layer.  You'll be able to mark a method as must override, and use a common interface class for all of them (which you'd then define a specific type for your override class as well.)

 

~Jon

Link to comment

How would you ever wire up to the must implement method if you haven't defined the interface?

For methods where I need to override but might conceivably require additional or different data, I personally would consider ditching the idea of specific arguments all together: have the connector pane with the usual dynamic dispatch and error I/O if required, plus an additional single/pair of terminals of some Object where descendant classes can cast if necessary?

Link to comment
In labview, if I wanted to do this, I'd probably use something very similar to the Actor framework where the interface for all methods is itself a class (i.e. the message type)  It basically creates an additional abstraction layer. 

 

This becomes syntactically burdensome and impractical. Dynamically-dispatched methods in this Command Pattern cannot readily accept/return unique parameters that are scoped locally to the caller (e.g., one method accepts a Boolean wire from the caller, while another accepts a Numeric wire). Additionally, this statefulness of the caller does not necessarily belong in the object just to circumvent this issue (now you have a LVOOP-style-clustersaurus).

 

Case study: try creating two user interfaces requiring request-response communication with Actor Framework (e.g., any sufficiently advanced SubPanel architecture), then examine the sequence diagram (timing diagram) of communication.

 

 

 

How would you ever wire up to the must implement method if you haven't defined the interface?

 

You cannot wire what is not created :-) Creating an "Implemented" method is the exact same workflow as creating a Static Dispatch method; it's just that the LVClass is broken before its creation, and happy once created. Unlike Must Override, which defines a both the name and parameters of a function prototype, a Must Implement would only require a name and leave parameters (ConPane I/O) up to the child class.

 

The parent class is saying "if you want to be like me, you have to do at least this; you can do it however you want, but you gotta do it."

 

Finally, the superclass could itself Implement and still mark itself as Must Implement -- just like Must Override. The subclass creating the Implemented method has access to the "Call Parent Method" LVOOP ability, which would effectively drop a static method of the parent implementation, while still reserving the freedom of defining its own new interface.

Link to comment
This becomes syntactically burdensome and impractical. Dynamically-dispatched methods in this Command Pattern cannot readily accept/return unique parameters that are scoped locally to the caller (e.g., one method accepts a Boolean wire from the caller, while another accepts a Numeric wire). Additionally, this statefulness of the caller does not necessarily belong in the object just to circumvent this issue (now you have a LVOOP-style-clustersaurus).

 

Case study: try creating two user interfaces requiring request-response communication with Actor Framework (e.g., any sufficiently advanced SubPanel architecture), then examine the sequence diagram (timing diagram) of communication.

 

Interesting, I take it you're not drinking the AF coolaide?  The arguement you're making hasn't been my experience, and one of my favorite applications of the AF IS a complicated Subpanel architecture.  If I had to knock the AF it would be more for removing compile time type safety on methods than anything else.  

Link to comment

Hmm. Jack, please understand I'm not trying to be hostile, I just really don't understand how this could be used.

So if a superclass deems MethodX must be implemented, but it can't call this method because no interface has been defined, how is the VI useful to the superclass or any other code that interacts with the superclass interface?

Something similar would be the ability to overload methods: being able to define a new VI with the same name but different connector pane. This however is mostly syntactic sugar as in languages that allow it as no real functionality is introduced that couldn't be achieved by naming each method differently as we do in LabVIEW. In effect overloading is really an edit-time convenience.

Link to comment
Hmm. Jack, please understand I'm not trying to be hostile, I just really don't understand how this could be used.

 

No worries! I would never think that. The burden's on me to provide a good enough example to show the value  :) (tl;dr -- skip to the example below the horizontal rule)

 

So if a superclass deems MethodX must be implemented, but it can't call this method because no interface has been defined, how is the VI useful to the superclass or any other code that interacts with the superclass interface?

 

A superclass is unable to call an Implemented method, just as a superclass is unable to call a static dispatch methods of its descendants. You know, the error "You have connected a refnum of one type to a refnum of another type and both types are members of some class hierarchy, but there is neither a simple up cast nor type cast between the two classes." So, I think your question indicates you're still seeing Implemented methods like a Dynamic Dispatch override. There's no sense of run-time polymorphism. It's just a static method in the subclass whose existence is necessitated by its parent. The parent says, "If you're going to have an IS A relationship to me, you gotta define this method. Implement it however you want, I don't need access to it and I'm never going to invoke it, I just gotta ensure you're taking care of business."

 

Something similar would be the ability to overload methods: being able to define a new VI with the same name but different connector pane. This however is mostly syntactic sugar as in languages that allow it as no real functionality is introduced that couldn't be achieved by naming each method differently as we do in LabVIEW. In effect overloading is really an edit-time convenience.

 

In the original post, I debated on whether to call this new option 'Must Implement' or 'Must Overload' or 'Must Supercede'. Implement seemed like the most correct term, since it's not overloading, per se (the method is in a separate namespace, and is only available to the Implementing class and its descendants -- an overloaded method seems like the overloading functions would have the same namespace and access scope, so overload seems like the wrong word).

 

Interesting, I take it you're not drinking the AF coolaide? The arguement you're making hasn't been my experience, and one of my favorite applications of the AF IS a complicated Subpanel architecture

 

On the contrary -- AF has disrupted the way I look at systems and interprocess messaging. Holistically, it's a hammer that shouldn't be swung at every nail, but the principles it teaches supercede the framework implementation itself. (To Jon: and we haven't talked in a while, I've contacted you to see if I can get a demo of your UI implementation with AF!)

 

I just really don't understand how this could be used.

 

Maybe it's a weak argument, but if one sees the value in "Must Override", that same magnitude of value exists with "Must Implement". It's just the parent's ability to ensure a functionality exists in descendants; one happens to have run-time polymorphism and a defined interface, the other doesn't.

 


 

Here's a simple example.

 

Consider the class, NotifyUser.lvclass which only has one method, DisplayMessage.vi, whose purpose is to display a string to a user. Later down the road, you consider it worthwhile to display other types of things to users, like Bools and Numerics, so you decide to subclass NotifyUser.lvclass since it's already got all the business logic for displaying messages. The illustration below shows this:

 

post-17237-0-02570900-1358099482_thumb.p

 

Notice how the two implementations have separate ConPanes from the parent. A need for separate ConPanes is always an indication that Dynamic Dispatch is the incorrect design choice, and I used to try to solve this (incorrectly) by weakly typing the inputs as variants or strings -- a bad API design choice. Also tried using classes, but then the same problem exists, just with a new abstraction layer added! (This is one of the syntax/logistical burdens of the Actor Framework implementation, and more generally the LVOOP approach to the Command Pattern in LabVIEW) That's where Must Implement saves us -- the ability to establish a relationship between child and parent methods, without requiring them to have the same interface.

 

Another thing to note above is that the two children are broken with the message "This VI attempts to override a static VI in an ancestor class." This is due to today's design limitation that subclasses cannot have the same method names as parent methods, except in the case of overrides. Further, note that in the middle diagram, use of the "Call Parent Method" is unrecognized. These two issues would be addressed by a "Must Implement" feature, shown below (note: this is not valid syntax with LabVIEW today, but through image manipulation we're able to demonstrate the proposed syntax)

 

post-17237-0-10425100-1358099919.png

 

Now, with "Must Implement", we have the ability to contractually require functionality in subclasses while maintaining the ability to extend parent class functionality, having acknowledged that Dynamic Dispatch is the incorrect tool when distinct function interfaces are desirable.

 

One final note to further stress the power of this new contractual relationship: "Must Implement" methods could additionally require "Implementations must call Parent Implementation", à la Dynamic Dispatch.

Link to comment

I have an immediate aversion to this idea but I can't quite put my finger on the reason "Why".

 

I think the combination of non-DD and the "Must implement" will simply lead to massive code smell where programmers just implement the required VIs as empty husks and do the rest of the work in the rest of the child class.

 

Why not have custom data interfaces with a dynamically overwritten "Do" command.  This enables custom front-loading while avoiding the code smell of the "Must override" function essentially being useless becuase the code does not need to be called at all. 

 

Shane.

 

 

PS Or emberace OOP and just make your variable input an object isntead of a primitive.  Remember what AQ says : Everything should be an object.  Of course then the task of "showing" belongs in this class and not your notifier class.  Always tell an object what to do instead of asking it for details and doing it yourself.

Edited by shoneill
Link to comment

This will also only work if the methods thus defined are private scope.  Otherwise LV cannot concievably know which versiont o execute in a real VI due to the inheritance probability for any given object control or indicator.  This ambiguity is normally handled by DD but since you explicitly don't want that, the handling must be performed by limiting the usage of the VI to the class which defines it.

 

I also don't quite understand the sentence: "Also tried using classes, but then the same problem exists, just with a new abstraction layer added!"  Can you elaborate on this a little?

 

Shane.

Link to comment

If I re-read your posts a few times I get the feeling you want to limit the types of messages a given actor can send and receive within the AF, is this correct?

 

I've posted the same question and I've been called mad for wanting something like that but for me it's the main reason why I do not use the AF.  I want to know at edit time if I'm trying to send an actor an incompatible message or not and the current AF does not allow for this because the message queues are too loosely defined.

 

In my experience you need to use a staggered inheritance to achieve what you want with the interface being re-defined at each inheritance level.  This means that all Boolean actory implement the boolean interface which accepts boolean messages.  If you try to send one of these to a Numeric actor, you get a broken wire.

 

Please see HERE and subsequently HERE for my take on this.

 

Shane

Link to comment
PPS One thing I WOULD like is the ability to have static class methods with the same name but different connector panes.  That would be übercool.

GAHH. No. Overloading is not cool. It is the source of tons of bugs in text based languages, and the only justification there is the ease of typing. In LabVIEW, we don't type the names of functions, so saving them with different names isn't a penalty, and it keeps accidental shadowing from happening. I dug into that one *extensively* when planning out LVOOP. For LabVIEW, there's no upside there.

 

 

The ability to aggregate several statics into a single selector in the palettes exists through poly VIs. That's a mechanism that could be more elegant, IMHO, but it does work if polymorphism in the editor is your concern.

Link to comment
I think the combination of non-DD and the "Must implement" will simply lead to massive code smell where programmers just implement the required VIs as empty husks and do the rest of the work in the rest of the child class.

 

Sounds like you need to fire that second-rate subclass designer  :o Just joking of course -- the goal of this language feature is to help convey information to developers about the intent of subclass design -- to help you implement the correct things. Not make things hard.

 

If you're attempting to subclass in a manner that far outside the original class designer's intent, it's perhaps time to consider composition rather than inheritance. That's your code smell.

 

If I re-read your posts a few times I get the feeling you want to limit the types of messages a given actor can send and receive within the AF, is this correct?

 

Nope!  :)

 

GAHH. No. Overloading is not cool.

 

Yeah, agreed. (And, AQ, what are your thoughts on Must Implement?)

 

On the other hand -- on the subject of 'same' names -- I see no reason one could not mark multiple methods from one subclass as Implementing a Must Implement parent method -- with the requirement they have unique filenames and therefore function names. Why is this desirable? To have access to the Call Parent Method; and to establish relationships and intent through native language features.

 

(This ties back to the same wish for overrides for Dynamic Dispatch, where a GUID property of the class is the basis for contract fulfillment of a 'Must' flag, rather than filenaming convention. Even writing this, I cringe thinking "Oh yeah, and development of this other GUID linkage feature gates the development of Implemented multiplicity..." Nevertheless...)

 

To illustrate with the Display Message example, DisplayMessage.vi could be Implemented by DisplayMessage-Bool-YesNo.vi and DisplayMessage-Bool-YeaNay.vi

 

post-17237-0-62322100-1358217053_thumb.p

 

You see that and think, "Aha! Canonical use case for subclassing NotifyUser-Bool.lvclass with NotifyUser-Bool-YeaNay.lvclass and NotifyUser-Bool-YesNo.lvclass and then overriding DisplayMessage.vi with Dynamic Dispatch! Gotcha, suckaaaah!" But what if we wanted a different flag on the ConPane to for YeaNay to print "Yay" for some dialects and "Yea" for others? We're back to a case where Dynamic Dispatch is just the incorrect tool.

 

Finally, these 'Must Implement' and related 'Require Implemented to invoke the Call Parent Method' features do not grant new abilities that cannot already exist by diligent convention. But I prefer compiler feedback to diligence or conventions  :thumbup1:

 

(EDIT: removing double post)

Edited by JackDunaway
Link to comment
I also don't quite understand the sentence: "Also tried using classes, but then the same problem exists, just with a new abstraction layer added!"  Can you elaborate on this a little?

 

That's a reference to the LVOOP implementation of the Command Pattern in LabVIEW, and its portly codebase. As a codebase grows, two other things grow greater-than-linearly: cognitive overhead required to understand a program, and the liability of a codebase owner. (And length of tea time, waiting for your build. But we like tea time.)

 

"Programs must be written for people to read, and only incidentally for machines to execute." --Abelson & Sussman, SICP, preface to the first edition

 

Another quote (that even Google cannot produce right now) says something about object-oriented and functional programming being roughly orthogonal, and the sweet spot of productivity for your language du jour comes by acknowledging the syntax and constructs of your language. It's just an opinion, but Command Pattern and subclassing every message is a beautiful and pure concept, but too close to the OO extrema to be practical. Syntactically and logistically burdensome.

 

[Crouching, waiting for tomatoes to be thrown]

  • Like 1
Link to comment

"So, I think your question indicates you're still seeing Implemented methods like a Dynamic Dispatch override."

 

No, I get it. You're looking for a statically resolved link. The possible paths code could take is completely resolved when things are compiled.

 

Note: I'm going to use the word "interface" a lot in this post, and I mean it as a general point of interaction between pieces of code, not the abstract sense which comes up in some languages that use it as a keyword, or in several theoretical discussions we have had here on lava.

 

I guess for me dynamic dispatch isn't fundamentally about just changing behavior via overrides or producing concrete implementation. Sure, that's the mechanics of it, but in isolation is of very little value.

 

A class that has any dynamic methods defines a programming interface at one level that derivative classes can modify or must implement. The value in such a mechanism comes when the programmer writes code calling the dynamic methods from the superclass interface-- completely unaware of any derivative classes. This code can be part of the superclass itself or completely separate. The code that operates on the dynamic interface at the superclass level is essentially laying down a series of hooks, detailing the conditions when these methods will be called and has done so completely decoupled from any derivative classes which may exist at run-time.

 

I suppose if I'm going to boil it down to one sentence it is this: just as important as the dynamic dispatch method itself is the contexts under which the method is called.

 

(You can at this point hopefully imagine how important I feel documentation is for these methods. I die a little inside every time I see an undocumented dynamic dispatch.)

 

So that's why I'm not sure I understand why a "must implement" could be useful. You're basically saying if you're going to have an "is a" relationship with me, you need to do something(). But an interface can't be provided so you can't provide the context in which something() will be called. No code that operates via the superclass interface can do anything with something() due to the lack of this interface. The code requires direct knowledge of the derivative class, which has completely defeated the purpose of defining something() at the superclass level.

 

I will concede one point though, a "must implement" will indeed provide a good set of clues as to what derivative classes should be doing. However I feel the inability to enforce anything beyond the mere existence of something with a given name means these hints really don't belong in code in my opinion.

  • Like 2
Link to comment
You're basically saying if you're going to have an "is a" relationship with me, you need to do something(). But an interface can't be provided so you can't provide the context in which something() will be called. No code that operates via the superclass interface can do anything with something() due to the lack of this interface. The code requires direct knowledge of the derivative class, which has completely defeated the purpose of defining something() at the superclass level.

 

Aha.

 

I understand. Had to read that many times, but I see we're probably coming from two different angles.  :lol:

 

The spirit of what I'm suggesting emphasizes how concrete classes interface with calling code. It's decidedly functional-programming-esque, not OO-purist by any stretch of the imagination. You're defending the case for OO-purism, where unknown concrete interfaces (ConPanes) of 'Must Implement' methods would be clearly incompatible with inversion of control, where superclasses must know the interface, by definition.

 

The usage of 'Must Implement' best jives with calling code that instantiate concrete, static classes. These concrete instances fundamentally represent functional programming, and incidentally enjoy the OO benefits of encapsulation/access scope/inheritance of abilities/and contractual requirements of subclassing (woot!). On the other hand, an OO-purist application might inject dependencies at runtime, where fundamentally the application is abstracted and transcended into a higher state of being.

 

Both approaches are valid! Yet if inversion of control is not an application domain requirement, I choose concrete implementations. Why? Static analysis by the compiler is your friend. +1 for compile-time errors vs. runtime errors 1446 or 1448.

 

That's all -- admittedly, the suggestion of 'Must Implement' is not OOP-y, and I'm still curious if any other languages address (either, have implemented, or have explicitly rejected) a notion such as 'Must Implement'.

 

And to quote you, 'please understand I'm not trying to be hostile' -- just laying it out there, and learning to be a better programmer like the rest of us!  :lol:  :yes:

Link to comment
That's all -- admittedly, the suggestion of 'Must Implement' is not OOP-y, and I'm still curious if any other languages address (either, have implemented, or have explicitly rejected) a notion such as 'Must Implement'.

 

Haven't read the whole thread (i.e the replies) as yet so might be going off half-cocked (as per usual). But is this definition (Must implement) just another name for abstract?

 

In an abstract class, you can also declare a method as abstract, which means that the method is not implemented and that any non-abstract subclass must implement it. An abstract method has no body:

Reference

Edited by ShaunR
Link to comment
Haven't read the whole thread (i.e the replies) as yet so might be going off half-cocked (as per usual). But is this definition (Must implement) just another name for abstract?

 

Reference

 

I believe the 'abstract' concept from other languages typically defines the full function prototype, including parameters. Which makes 'abstract' more akin to Dynamic Dispatch than Must Implement. I'm suggesting Must Implement does not define the function parameters for subclasses.

 

(But perhaps Must Implement does require a minimum set of parameters; the object input, for instance, would be required in order to invoke 'Call Parent Method' <headscratch>gotta chew on that one</headscratch>).

 

(And a sincere virtual+1 to you for joining this thread without using the term LVPOOP :lol: Perhaps the term 'functional programming' piqued your interest  :D Just ribbing.)

Link to comment
Haven't read the whole thread (i.e the replies) as yet so might be going off half-cocked (as per usual). But is this definition (Must implement) just another name for abstract?

 

Reference

 

As far as I understand it, abstract methods always define at least the interface (parameter list) but what Jack seems to want is a super-abstract definition that just defines the method name without any interface. How that could possibly be useful I can't really understand as nobody can use this method, except the class implementing it (and possibly classes inheriting from the implementing class), so why even force the inherited class to implement a specific method?

 

I use abstract methods in Java and C++, if I want to have a method that I can call from the parent class but which needs to be implemented by the inherited class, but for super-abstract methods that couldn't work since the parent doesn't know how to call it. So what would it bring me then at all?

 

Another use of abstract methods is to provide an abstract parent class that defines a common method all children need to implement in order for any client of any of the actual implementation classes to be called. One could define an empty method in the parent that all children can override, but an abstract method forces the implementor of a child to provide a method implementation, while an empty method could be forgotten and then produces unnecessary errors.

 

Maybe a more loosely typed language could benefit from such a concept, but LabVIEW, C(++), and Java only can use a function/method if the interface is fully known (vararg functions in C and Java being a somewhat special case here and rarely implemented by programmers outside the runtime libraries itself).

 

Maybe you need to go with Lua then, where even functions are just another object! :D

Link to comment
The ability to aggregate several statics into a single selector in the palettes exists through poly VIs. That's a mechanism that could be more elegant, IMHO, but it does work if polymorphism in the editor is your concern.

 

I think here we may have some significant common ground.

 

Regarding overloading: From a user point of view:

If you already have a specific object wired up in your program (with static "Init" function following the object constant) and you want up change the object type then you also have to go and search for the "Init" function for the new class, it won't update automatically because it's got a different name.  I don't actually care what name it has, I'd just like such operations to automatically find the related VI for my new class.  I would inagine some secondary identifier for class functions aside from the filename, like "Ability" or something which would allow the IDE (And only the IDE) to perform such swap-out operations on otherwise unrelated class functions.

 

That's all, it's not a major headache, it's not a showstopper it's just behaviour I run into all the time where I think it could be solved so much easier.

 

Shane.

 

PS I think there's some common ground between this idea and Jack's also.  Adding "Ability" tags for static VIs and telling child classes they MUST IMPLEMENT those abilities reaches the same target without having to have functions with the same name and different connector panes, no?

Edited by shoneill
Link to comment
Sounds like you need to fire that second-rate subclass designer  :o Just joking of course -- the goal of this language feature is to help convey information to developers about the intent of subclass design -- to help you implement the correct things. Not make things hard.

 

Your proposed enforcement is an illusion.  Due to the code not having any interface representation it may never be executed.  Not being able to compile a class just because of a missing VI prototype which is (quite possibly) never called seems seriously flawed to me.

 

Your proposal sounds like my wife.  She often not only wants me to do something (lets think of this as the interface) but she also wants me do do it her way (your enforcement) even though this has no bearing on the start or end status of the operation.  I've never had the spontaneous idea that this was a good thing.  When finished, if she asks me if I did it "her way" then of course the temptation is to say "Of course dear" event hough you know it's not true.  If a class is in the position to do WHAT you want, why is it important that it does it your way?

  • Like 1
Link to comment
Your proposal sounds like my wife.  She often not only wants me to do something (lets think of this as the interface) but she also wants me do do it her way (your enforcement) even though this has no bearing on the start or end status of the operation.
You can't win an emotional argument with logic!
  :P
Edited by ShaunR
Link to comment

I believe the 'abstract' concept from other languages typically defines the full function prototype, including parameters. Which makes 'abstract' more akin to Dynamic Dispatch than Must Implement. I'm suggesting Must Implement does not define the function parameters for subclasses.

 

(But perhaps Must Implement does require a minimum set of parameters; the object input, for instance, would be required in order to invoke 'Call Parent Method' <headscratch>gotta chew on that one</headscratch>).

 

(And a sincere virtual+1 to you for joining this thread without using the term LVPOOP :lol: Perhaps the term 'functional programming' piqued your interest  :D Just ribbing.)

IC.

 

I have actually come across this instance before where it was frustrating that I couldn't have different terminals for an override. It forced me to have "dummy" terminals which were only functional in certain overrides which (to my mind) was unnecessarily confusing and meant more documentation.

 

.

 

(I didn't use LVPOOP because I wasn't talking about LV  :D  )

Edited by ShaunR
Link to comment
IC.

 

I have actually come across this instance before where it was frustrating that I couldn't have different terminals for an override. It forced me to have "dummy" terminals which were only functional in certain overrides which (to my mind) was unnecessarily confusing and meant more documentation.

 

.attachicon.gifUntitled.png

 

(I didn't use LVPOOP because I wasn't talking about LV  :D  )

 

But how could you define a super-abstract method and use it anywhere except in the implementor of that method (and possibly inherited classes from the implementor)? LabVIEW, C(++) and Java all have a parameter interface that is defined at compile time, so needs to be well known when compiling and therefore no one who doesn't see the full interface definition of a method can possibly use it.

C allows some trickery with function pointer casting but that is not only ugly but outright dangerous. C++ is much more strict in that sense and normally doesn't allow function pointer casts just as Java, which doesn't really know anything about casting other than between compatible objects.

 

Lua goes in fact into that direction, as functions are themselves full objects and can have variable number of arguments, with a function always knowing how many parameters it was passed to (and it of course shouldn't try to retrieve more parameters from the stack than it got passed, but the Lua engine protects that). In addition return parameters of functions are always returned as function return values and yes a function can have 0, 1, or any other number of return values too.

Link to comment
But how could you define a super-abstract method and use it anywhere except in the implementor of that method (and possibly inherited classes from the implementor)? LabVIEW, C(++) and Java all have a parameter interface that is defined at compile time, so needs to be well known when compiling and therefore no one who doesn't see the full interface definition of a method can possibly use it.

C allows some trickery with function pointer casting but that is not only ugly but outright dangerous. C++ is much more strict in that sense and normally doesn't allow function pointer casts just as Java, which doesn't really know anything about casting other than between compatible objects.

 

Lua goes in fact into that direction, as functions are themselves full objects and can have variable number of arguments, with a function always knowing how many parameters it was passed to (and it of course shouldn't try to retrieve more parameters from the stack than it got passed, but the Lua engine protects that). In addition return parameters of functions are always returned as function return values and yes a function can have 0, 1, or any other number of return values too.

Well. I think you mentioned something earlier about varArgs and PHP (which admittedly may be easier because it is interpreted at run-time) has the capability to accept variable length arguments (func_get_args). Like most of these sorts of things, I don't care how it's implemented; that's not my job. However, it would be nice if it did.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.