Overloading is defining multiple methods with same name but different number of parameters and different datatype of parameters
Overriding is redefinition of base class function in its derived class with same signature i.e return type and parameters
For operators, some methods must have been defined in base classes and when we redefine those methods in our classes, we call them operator overloading. However, shouldn't it be called operator overriding? Also, we cannot change the parameters of the methods, so isn't operator overloading more similar to overriding?
I am really confused in this very basic thing.
It is not overriding, because you are not changing the functionalities of existing operators. For example, you can't change what 1 + 1 does with operator overloading.
What operator overloading allows you to do is to define new operators. For example, you can define a + that operates on two int arrays (assuming your language doesn't already support this). If you think of the + operator as a function, the existing + operators might have signatures:
double +(double, double)
int +(int, int)
string +(string, string)
Now you are adding a new operator:
int[] +(int[], int[])
These "functions" all have the same name + but different parameters. This is similar to the situation in overloading, so the language feature is called operator overloading.
Related
I would like to produce SQL that is essentially the equivalent of array[] or [] using jOOQ's DSL so that it's portable between dialects.
Unfortunately in Kotlin, none of these work:
// Overload resolution ambiguity. All these functions match.
// public open fun <T : Any!> array(vararg values: TypeVariable(T)!): Field<Array<(out) TypeVariable(T)!>!> defined in org.jooq.impl.DSL
// public open fun <T : Any!> array(vararg fields: Field<TypeVariable(T)!>!): Field<Array<(out) TypeVariable(T)!>!> defined in org.jooq.impl.DSL
DSL.array()
DSL.array(null as Any?) // Produces a non-empty array
DSL.array(emptyList<Any>()) // Produces a non-empty array
Is there any way to do this, or something like an DSL.emptyArray() method?
Why passing emptyList<Any> didn't work
The Collection accepting overload of DSL.array() expects a Collection<? extends Field<T>>, i.e. a collection of column expressions, not a Collection<? extends T>, which would be a collection of bind values. We can't have both overloads for the usual type erasure reasons, so only the more generic version is offered. But you're passing a List<Any>, not a List<Field<*>>. You could change your code to:
DSL.array(emptyList<Field<*>>())
Why passing null didn't work
When you pass null, the varargs overload is resolved, which corresponds to ARRAY[NULL] in SQL, an array containing a NULL value.
How to call the varargs overload
If you want to work with the varargs overloads, then just pass an empty array:
DSL.array(arrayOf<String>())
Because array types are reified in Java, both varargs overloads exist:
array(T...): Accepting bind values
array(Field<T>...): Accepting column expressoins
Regarding array types
If you're using PostgreSQL, you'll probably have to cast that array expression explicitly to e.g. SQLDataType.VARCHAR.getArrayDataType()
DSL.array(arrayOf<String>()).cast(SQLDataType.VARCHAR.getArrayDataType())
Using bind values as an alternative
You can always use bind values or inline values as well:
DSL.value(arrayOf<String>())
DSL.inline(arrayOf<String>())
In this case, the array type is known to jOOQ, and you don't need to cast it explicitly anymore.
To get the class definition to be used for example for json deserialization the following can be used in Kotlin:
Map::class.java
A example usage is the following:
val map = mapper.readValue(json, Map::class.java)
But now how to have the generic type definition?
Something like this does not compile:
val map = mapper.readValue(decodedString, Map<String, String>::class.java)
So my question is: What is the generic equivalent to *::class.java
Class<T> (in Java) or KClass<T> (in Kotlin) can only represent classes, not all types. If the API you're using only uses Class<T> or KClass<T>, it simply doesn't support generic types (at least in those functions).
Instead, KType (or Type in Java) is the proper type to use to represent the complete type information including generics. You could use it this way:
val myMapType: KType = typeOf<Map<String,String>>()
Unfortunately, KType doesn't have a type parameter (it's not KType<T>), and that makes it impossible to use for compile-time type checking: you can't have the equivalent of fun deserialize(Input, KClass<T>): T using KType instead of KClass, because you can't define the T for the return type by using only a KType argument.
There are several tricks to work around this:
In both Java and Kotlin, one of the ways is to get this information through inheritance by providing a generic superclass and inheriting from it.
In general, serialization APIs (especially the deserializing part) provide workarounds using this, such as Jackson's TypeReference or Gson's TypeToken. It's basically their version of Type but with a type parameter to have some compile-time type safety.
In Kotlin, there is sometimes another way depending on the situation: making use of reified type parameters. Using inline functions, the compiler can know more information at compile time about the type parameters by replacing them with the actual inferred type at the call site when inlining the function's body. This allows things like T::class in the inline function's body. This is how you can get functions like typeOf to get a KType.
Some Kotlin-specific APIs of deserialization libraries use inline functions to remove the hassle from the user, and get type information directly. This is what jackson-module-kotlin does by providing an inline readValue extension without a Class argument, which reifies the type parameter to get the target type information
In Kotlin, a function with at least one argument can be defined either as a regular non-member function or as an extension function with one argument being a receiver.
As to the scoping, there seems to be no difference: both can be declared inside or outside classes and other functions, and both can or cannot have visibility modifiers equally.
Language reference seems not to recommend using regular functions or extension functions for different situations.
So, my question is: when do extension functions give advantage over regular non-member ones? And when regular ones over extensions?
foo.bar(baz, baq) vs bar(foo, baz, baq).
Is it just a hint of a function semantics (receiver is definitely in focus) or are there cases when using extensions functions makes code much cleaner or opens up opportunities?
Extension functions are useful in a few cases, and mandatory in others:
Idiomatic Cases:
When you want to enhance, extend or change an existing API. An extension function is the idiomatic way to change a class by adding new functionality. You can add extension functions and extension properties. See an example in the Jackson-Kotlin Module for adding methods to the ObjectMapper class simplifying the handling of TypeReference and generics.
Adding null safety to new or existing methods that cannot be called on a null. For example the extension function for String of String?.isNullOrBlank() allows you to use that function even on a null String without having to do your own null check first. The function itself does the check before calling internal functions. See documentation for extensions with Nullable Receiver
Mandatory Cases:
When you want an inline default function for an interface, you must use an extension function to add it to the interface because you cannot do so within the interface declaration (inlined functions must be final which is not currently allowed within an interface). This is useful when you need inline reified functions, for example this code from Injekt
When you want to add for (item in collection) { ... } support to a class that does not currently support that usage. You can add an iterator() extension method that follows the rules described in the for loops documentation -- even the returned iterator-like object can use extensions to satisfy the rules of providing next() and hasNext().
Adding operators to existing classes such as + and * (specialization of #1 but you can't do this in any other way, so is mandatory). See documentation for operator overloading
Optional Cases:
You want to control the scoping of when something is visible to a caller, so you extend the class only in the context in which you will allow the call to be visible. This is optional because you could just allow the extensions to be seen always. see answer in other SO question for scoping extension functions
You have an interface that you want to simplify the required implementation, while still allowing more easy helper functions for the user. You can optionally add default methods for the interface to help, or use extension functions to add the non-expected-to-be-implemented parts of the interface. One allows overriding of the defaults, the other does not (except for precedence of extensions vs. members).
When you want to relate functions to a category of functionality; extension functions use their receiver class as a place from which to find them. Their name space becomes the class (or classes) from which they can be triggered. Whereas top-level functions will be harder to find, and will fill up the global name space in IDE code completion dialogs. You can also fix existing library name space issues. For example, in Java 7 you have the Path class and it is difficult to find the Files.exist(path) method because it is name spaced oddly. The function could be placed directly on Path.exists() instead. (#kirill)
Precedence Rules:
When extending existing classes, keep the precedence rules in mind. They are described in KT-10806 as:
For each implicit receiver on current context we try members, then local extension functions(also parameters which have extension function type), then non-local extensions.
Extension functions play really well with the safe call operator ?.. If you expect that the argument of the function will sometimes be null, instead of early returning, make it the receiver of an extension function.
Ordinary function:
fun nullableSubstring(s: String?, from: Int, to: Int): String? {
if (s == null) {
return null
}
return s.substring(from, to)
}
Extension function:
fun String.extensionSubstring(from: Int, to: Int) = substring(from, to)
Call site:
fun main(args: Array<String>) {
val s: String? = null
val maybeSubstring = nullableSubstring(s, 0, 1)
val alsoMaybeSubstring = s?.extensionSubstring(0, 1)
As you can see, both do the same thing, however the extension function is shorter and on the call site, it's immediately clear that the result will be nullable.
There is at least one case where extension functions are a must - call chaining, also known as "fluent style":
foo.doX().doY().doZ()
Suppose you want to extend the Stream interface from Java 8 with you own operations. Of course, you can use ordinary functions for that, but it will look ugly as hell:
doZ(doY(doX(someStream())))
Clearly, you want to use extension functions for that.
Also, you cannot make ordinary functions infix, but you can do it with extension functions:
infix fun <A, B, C> ((A) -> B).`|`(f: (B) -> C): (A) -> C = { a -> f(this(a)) }
#Test
fun pipe() {
val mul2 = { x: Int -> x * 2 }
val add1 = { x: Int -> x + 1 }
assertEquals("7", (mul2 `|` add1 `|` Any::toString)(3))
}
There are cases where you have to use extension methods. E.g. if you have some list implementation MyList<T>, you can write an extension method like
fun Int MyList<Int>.sum() { ... }
It is impossible to write this as a "normal" method.
is operator overloading in fact polymorphism or parameter overloading?
Is it true that polymorphism usually refer to different classes responding to the same "message" (the method name) and do different things, so
bird.give_sound()
and
car.give_sound()
can do different things. And parameter overloading is more about talking about the same class, doing different things when the parameters sent along with the message (the method name) are different. So
bird.give_sound()
and
bird.give_sound(:frighten_sound)
can be different.
So operator overloading is strictly parameter overloading? like this following:
"foo" + "bar"
"foo" + 3
at least in Ruby, it is sending the + message to the string containing foo, the first line is sending with a parameter string, the second one is sending a parameter 3, and the + do slightly different things, but it is the same receiver class String
In the following example, it is polymorphism:
"foo" + 3
1 + 3
because the + message invoke different methods of different classes, but using the same message name +. So in these 2 cases, they are polymorphism, not operator overloading?
Is the above accurate and correct? Is there something that might be added to it or be corrected above?
Thank you for the clarification of context in your comment. Yes, I would say you are correct.
To summarize as short as possible...
Given identical method name (or "message"):
different behaviour based on parameter type is overloading,
different behaviour based on object type is polymorphism.
I'm going to take a stab in the dark and say that it's kind of (but not really) both.
Each object has to deal with the given object (the object on the right side of the operator) in a specific way. With strings, it seems that the toString method (or other language equivalent) would be used. So you would always be appending a string (passed to the method as an Object). (Polymorphism)
However, your object may need to perform different logic based upon the object given. For example, say you have a Student object. You may have one version of the method that takes a Class object, and adds it to the Student's class schedule. You then might have an overload that takes, say, a Book and adds it to the Student's collection of required reading material. (Parameter Overloading)
Polymorphism is when one data type dynamically behaves as another datatype.(Dynamic typecasting)
Shape
Qudrilateral
Rect
Rhombus
Elliptoid
Oval
Circle
Polymorphism is automatically selecting the proper area() method for a given object context
Operator overloading is when you select the correct area method for a method context(i.e. number of arguments passed or type of arguments passed) So if Rect had two area methods, one that accepted one argument(square) and one that accepted two arguments(any other rectangle)
So depending on the usage context, defining the operators for a given object can result in either Polymorphism or Operator Overloading.
Good Question.
The problem you found, its that we have 2 different concepts which similar syntax, that clash when applied programming: Overloading and parameter inheritance.
When I found operator overloading, I usually think in terms of overloading (methods) functions, to make more clear.
When I read these:
// (string) x = (string) "foo" + (int) 3
x = "foo" + 3
I think of these:
// (string) x = (string) "foo".concat((int) 3)
x = "foo".concat(3)
There is an additional problem, that each programming language handles operators with classes different.
I would suggest, to avoid operator overloading with object parameters, and explicity use functions.
consider a standard c# 'function'
public void foo()
{
//some code
}
In c or c++ this is called a 'function' - even if taking no parameters and returning no value. In another language maybe it would be a 'procedure'.
In object orientation speak it would be called a 'method' if a class member.
What would be the correct term to use in c#?
Method : function of a class.
Function : function out of a class, possible only in full-object languages (like C++, C, etc.)
Procedure : function that return nothing/void. I personnaly don't like this word, I'd rather use 'function'
Make your choice =)
Edit : Just to be more precise, Method, function and procedure are OOP words to describe a subroutine. Some languages have their own vocabulary such as "predicate" in Prolog, or "constructor" in C++/C#/Java, or even "property" in C#.
Just to confuse the issue futher: (from C# Language Specification)
7.4 Function members
Function members are members that contain executable statements. Function members are always members of types and cannot be members of namespaces. C# defines the following categories of function members:
* Methods
* Properties
* Events
* Indexers
* User-defined operators
* Instance constructors
* Static constructors
* Destructors
And
10. Classes
A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, destructors and static constructors), and nested types. Class types support inheritance, a mechanism whereby a derived class can extend and specialize a base class.
So "function member" or "method" would be correct for C#.
Method is OOP abstraction term. They describe behaviour(a verb) of an object.
They are equivalent to some of the procedural programming's functions and procedures.
(the properties etc are also function and procedures).
So, function is a program within program that returns some values.
Procedure is a program within program that does something.
Methods, Properties etc, etc are a next level of abstraction(used in OOP). They are wrapped around functions and procedures.
I think in C# call it a method because C# is object oriented language.
If a "Function" is part of a class I call it a method.
If I was coding in C (i.e. in proceedural or non OO idiom) I call it a function.
I personally don't use the word proceedure to refer to a "Function"
I thought (in Ada) that a 'procedure' is the correct term generally, and a 'function' is a procedure which is guaranteed to be side-effect free, that is, it only reads from and does manipulation on data, and returns it, but does not write anything or have any 'side-effects'.
I'm a Java guy anyway, I call everything a function even though it should be called a method.
I think method is the correct term, but I doubt you'll get any funny glares for using any of the other suggested names.
Since I spent a lot of time with ADA I would call that a "procedure" since it has no return value. If it had a return value, I would have called it a "function".
I've never seen the point of saying "Method", though that is most likely the correct term to use when talking about functions/procedures that are members of a class. Never really saw the use of yet another term for the same thing.