HTTP-Based OOP, Inheritance, and Polymorphism
Is anything magical about polymorphism that requires OOP? Good old HTTP can just as easily apply polymorphism and inheritance - possibly even BETTER - than OOP.
Join the DZone community and get the full member experience.
Join For FreeThis might sound like a joke, but it's actually not. First, let's define inheritance. Inheritance is the ability to use polymorphism to override a method with another implementation. You inherit from a class, and you override one of its virtual functions. This results in that code having an object that will no longer invoke the old base class method, but rather the new overridden method. Kind of easy, right?
Polymorphism Is the Ability To Have Old Code Invoke New Code
Well, there's nothing intrinsically special about class-based OOP that prevents you from implementing the above in a functional context. In a functional programming language, you can have a reference to a function, and replace the function it's pointing to, before passing in your function reference to some method in need of a function with the specified signature. This achieves the exact same result as "classic polymorphism."
Then realize that HTTP endpoints are fundamentally just "functions." Sure, there's the HTTP protocol and some networking in the picture, but you've got a URL, you're passing in your arguments (JSON payload), and invoking it more or less like a function, only to then use the returned JSON somehow. Now imagine you can exchange the URL, and you've basically got "overriding" capabilities in HTTP: zero classes, zero (classic) polymorphism, and zero OOP. Still, it provides you with the exact same thing as traditional OOP. In addition, your "inherited" HTTP endpoint can still invoke your "base class" endpoint. The last parts become the equivalent of "super(args)" from more traditional OOP mechanisms.
Now watch the following video where I illustrate the concept. In this video, I walk you through a very specific use case where you want to "override" an existing HTTP to add support for Stripe payments.
Interestingly, this allows you to use Hyperlambda to override "base class methods" written in any programming language, including Python, PHP, C#, or Java, for that matter. The method to invoke the "base class method" is a standardized protocol, HTTP that is, passing in JSON back and forth. Below is one of the code files I am using in the above video. The concepts are the same in all files, so one file should let you understand the basics.
.arguments:*
.description:Interceptor invoking Stripe to create a Stripe customer, for then to attach the customer ID to specified payload, before invoking intercepted endpoint.
/*
* Invoking Stripe to create a customer for then to attach
* the customer ID to the payload we're passing in to the
* original endpoint, before invoking intercepted endpoint
* now with a Stripe Customer ID, allowing you to associate
* the user internally with a Stripe customer object.
*/
.before
/*
* If you're using automatic tax calculations, you'll
* need to pass in the IP address of the client - At
* which point you'll have to uncomment the line of
* code below, and pass it into slot invocation.
*/
request.headers.get:X-Real-IP
// Sanity checking invocation.
validators.mandatory:x:@.arguments/*/name
validators.mandatory:x:@.arguments/*/email
validators.email:x:@.arguments/*/email
// Invoking Stripe API.
unwrap:x:+/*
signal:stripe.customers.create
name:x:@.arguments/*/name
email:x:@.arguments/*/email
ip_address:x:@request.headers.get
// Attaching Stripe's customer id to the payload.
unwrap:x:+/*/*
add:x:../*/http.post/*/payload
.
stripe_customer_id:x:@signal
// Evaluating Stripe lambda object.
eval:x:@.before
// Endpoint we're intercepting.
.endpoint:"https://tiger-polterguy.gb.aista.com/magic/modules/stripe-interceptor/echo"
/*
* Checking if we've got an Authorization HTTP header,
* at which point we forward it to the original HTTP endpoint.
*/
request.headers.get:Authorization
if
not-null:x:@request.headers.get
.lambda
add:x:../*/http.post/*/headers
.
Authorization:x:@request.headers.get
// Forwarding arguments given to endpoint to intercepted endpoint.
add:x:../*/http.post/*/payload
get-nodes:x:@.arguments/*
// Invoking the intercepted HTTP endpoint.
http.post:x:@.endpoint
headers
Content-Type:application/json
convert:true
payload
// Returning the intercepted endpoint's status code.
response.status.set:x:@http.post
// Returning response payload from intercepted endpoint to caller.
add:x:+
get-nodes:x:@http.post/*/content/*
return
Since Hyperlambda is 100% dynamic, allowing you to declare an endpoint taking "whatever," this allows you to modify the code in your overridden HTTP endpoint and your client consuming your interceptor endpoint, without needing to modify the intercepter endpoint. Pretty cool, huh?
Who Said We Needed OOP To Do Polymorphism?
I refer to the idea as HTTP interceptors, but it's fundamentally extremely similar to "classic OOP and inheritance," except of course a bajillion times more powerful because I can use Hyperlambda to "override" a method written in Java, C#, PHP, Python, GraphQL, or "whatever" really.
Opinions expressed by DZone contributors are their own.
Comments