I want use generic interfaces that will be specified by their implementing classes, and all in all this has been working fine, like:
interface Remove <E> { fun remove(entity: E) }
class MyHandler : Remove <MyClass> {
override fun remove(entity: MyClass) { */do stuff/* }
}
However, I have a case (so far, expecting more to come) where I want the function itself to be generic. Writing the interface is no problem at all:
interface FindByID <E> { fun <K : Serializable> findByID(id: K): E }
I need K to be serializable because that's a requirement of some function I need to call.
The compiler doesn't seem to agree with my implementation attempt. When I do this:
override fun <String> findByID(id: String): User {
return someFunction(User::class.java, id) as User
}
I get two compiler errors:
overrides nothing
id is not Serializable
However, when I remove override and <String> from the signature, it works fine. This means String is serializable, which my research shows as well.
What seems to be the problem here?
Also, yes, I know that I could work around this issue in a couple of ways, like
making the interface function accept Serializable instead of <K : Serializable>
not specifying K on override, but on call (myHandler.findByID<String>("myID"))
"rerouting" the call, implementing (not overriding) in MyHandler a function that accepts Strings and then internally calls the overriden function
Although open to suggestions, I'm less interested in workarounds, but would rather like to understand and (if possible) solve the actual problem or at least know it can't be done so I can take that into account for planning
The current problem
With your current declaration of <String>, you're not specializing the type parameter as you might think. What you're actually doing is declaring a type parameter that happens to be named String (nothing to do with the well-known String type, just an unfortunate name collision). With syntax coloring, you should see that String here is in the color of a type parameter, not the same color as the String type would be. Change this name to anything else, and you'll realize the confusion.
So if we rename this to K, the problems become obvious: problem 1 "overrides nothing" is because your generic type parameter doesn't have the same : Serializable constraint as the findByID method defined in the interface. And problem 2 stems from it.
Solutions
Also, yes, I know that I could work around this issue in a couple of ways, like
not specifying K on override, but on call (myHandler.findByID("myID"))
This point is actually the essence of the issue, not a workaround: defining a generic function in your interface actually makes it part of the contract for this function to be generic.
Implementations must have a generic type parameter here.
What to do to fix it depends on what you expect to happen.
If you're ok with having generic functions in your implementations, then leave the interface as you declared it, but accept that the implementations have to deal with all possible values of K, which is most likely not what you want here.
If you want to define a specific type in your implementations, K should be part of the interface definition (not the interface method), and the method should not have a type parameter itself, but simply accept the existing K from the interface:
interface FindByID<E, K : Serializable> {
fun findByID(id: K): E
}
Regarding data classes it is forbidden to not use var or val keywords in the primary constructor, i.e. every parameter is implicitly turned into a class property. However, sometimes there are cases which I don't want each parameter to be turned into a class property.
So, as far as I can see, there is no chance of passing a parameter in a primary constructor that is accessible only within the constructor and is forgotten after the construction of the instance has finished. Is there a good reason for this?
The only way I see to get around this, is not to use data classes or to use a secondary constructor that allows for non-var/val-prefixed variables. However, having a lot of parameters that need to be passed, a secondary constructor would immensely inflate the class. Of course, I could wrap all the parameters into another object, but that would just kind of shift the problem to another place.
Is there a recommended approach or pattern in order to cope with that?
You are not limited at all, you just have to do things a bit differently.
Data classes are intended to be very clear about what they contain and in what order, and only allow members in the primary constructor parameter list.
But you have other options: use a secondary constructor, and/or create top-level functions with the same name as the class with different overloads, or create factory methods in the companion object:
data class Person(val name: String, val age: Int) {
// secondary constructor
constructor (name: String): this(name, 0) {
// ... make a newborn
}
// factory methods in companion object
companion object {
fun of(name: String, birthdate: LocalDate): Person {
return Person(name, yearsSince(birthdate))
}
}
}
// function with same name as class acting like a constructor
fun Person(name: String, birthdate: LocalDate): Person {
return Person(name, yearsSince(birthdate))
}
// these all work now:
Person("Fred", 30) // primary constructor
Person("Baby") // secondary constructor
Person("Geoff", LocalDate.parse("12/08/1990")) // top-level function
Person.of("Jennifer", LocalDate.parse("01/01/1981") // companion function
You can also hide the primary constructor by making it private, but you cannot hide the copy version of that constructor.
By the way, having data classes with this contract for the primary constructor really help serialization/deserialization libraries know what to do with the class that would be guesswork otherwise. It is a good thing!
Fist thing that I must say is that this is my personal opinion so take it with grain of salt.
From official kotlin documentation
We frequently create classes whose main purpose is to hold data. In such a class some standard functionality and utility functions are often mechanically derivable from the data.
So data classes are supposed to be used as data holders, and they shouldn't contain much logic.
From my perspective when you want to pass something to constructor but class doesn't store that data then there is probably some logic connected with that.
Common situation when you want to do this is:
Using some flag to change behavior of constructor
Passing some class that wraps all data needed and then extract it to each individual field.
In first case then we clearly see that this isn't part of data class use case.
And second case is simply bad code, it introduces unneeded dependency on another class and hides what that class actually needs.
Constructors should be simple, they take data that class requires and bind it to fields, not much logic should reside there, it should be up to those that use constructor to prepare all data, and if there is some repeatable code when creating new instances then it might be good idea to use factory method to encapsulate that.
In ActionScript 3.0, this compiles:
public function set func(value:Function):void
{
}
public function func():void
{
}
This doesn't:
public function set someVar44(value:int):void
{
}
var someVar44:int;
Why does the first one compile? I suppose it's possible that Adobe just specifically and arbitrarily decided to block this for variables and to allow it for functions, but allowing it for either functions or variables doesn't seem to make any sense. I'm suspicious there's more to the story here. What am I not seeing?
This is really interesting, and took a fair amount of digging to get down to (although the answer seems painfully obvious).
As you know variables/properties cannot be declared in the same scope with identical names. Therefore the set function someVar44() and the variable someVar44 are in direct conflict (besides issues with trying to initialize the variable twice). Conversely if you had tried:
public function get func(value:Function):void
{
}
you would have ran into a similar issue with a duplicate function definition error. So why does the set function seem to allow you to get past these errors? As setters and getters are known for accessing and mutating properties of a class, it would seem they are also treated as class properties as opposed to a typical method, but this is not entirely the case. In fact, only the setter appears as a property of the public interface, the getter on the other hand is a method that can read like a property.
The setter:
public function set func(value:Function):void
Is read exactly like a property of the object, and without any other properties in direct conflict with it (i.e. - there is no current property like var func.) you do not receive a compiler error.
From adobe:
set Defines a setter, which is a method that appears in the public interface as a property.
get Defines a getter, which is a method that can be read like a property.
I believe that is why you are not getting a compiler error with set method. Although if you attempt to access that set method, the priority is immediately assumed to the function func(). That is, if you attempt this.func = function():void { } you will get the error:
Error #1037: Cannot assign to a method func
I can understand logically why the first compiles (in the older compiler). When considering an instance of the object, getting the obj.func property should return the member function you've defined, while setting the obj.func property should call the setter you've defined. This doesn't seem to be an ambiguity to me, though as we've seen, the runtime disagrees with me.
In the second case, you've defined a var (which defaults to the internal scope since you didn't say public, but that's another story) which, being externally visible, implicitly defines a getter and setter. So if someone sets the obj.someVar44 property of your object, are they calling the setter or setting your variable value? It's clearly an ambiguity and a duplicate definition.
Please tell me why the constructor does not return any value. I want a perfect technical reason to explain to my students why the constructor does not have any return type.
What actually happens with the constructor is that the runtime uses type data generated by the compiler to determine how much space is needed to store an object instance in memory, be it on the stack or on the heap.
This space includes all members variables and the vtbl. After this space is allocated, the constructor is called as an internal part of the instantiation and initialization process to initialize the contents of the fields.
Then, when the constructor exits, the runtime returns the newly-created instance. So the reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the memory allocation and object initialization code in the runtime.
Its return value (if it actually has one when compiled down to machine code) is opaque to the user - therefore, you can't specify it.
Well, in a way it returns the instance that has just been constructed.
You even call it like this, for example is Java
Object o = new Something();
which looks just like calling a "regular" method with a return value
Object o = someMethod();
How is a constructor supposed to return a return value? The new operator returns the newly created instance. You do not call a ctor, newdoes it.
MyClass instance = new MyClass();
If the ctor would return a value, like so:
public int MyClass()
{
return 42;
}
Where would you receive the integer?
(I'm biased towards C++, so regarding other languages, take this with a grain of salt.)
Short answer: You don't want to have to explicitly check for success for every single object construction in your code.
Somewhat longer answer: In C++, constructors are called for dynamically as well as for globally and automatically allocated objects. In this code
void f()
{
std::string s;
}
there is no way for the constructor of s (std::string::string()) to return any value. Either it succeeds - then we can use the object, or it throws an exception - the we never get a chance to try to use it.
IMO, that's the way it should be.
A constructor is some method automatically called when you initialize a new instance of an object.
This method is there if you need to initialize your object to a given state and run few default methods.
Actually you can imagine the constructor always return the instance of the object created that would be a good image.
When you call a constructor the return value is the new object:
Point pt = new Point(1,2);
But within the constructor itself, you're not actually creating and returning the object; it's been created before your code starts, you're just setting up the initial values.
Point::Point(int x, int y) {
this->x = x;
this->y = y;
}
The lack of a return type reflects the fact that constructors are used differently than other functions. A return type of null, while technically accurate, doesn't reflect well the fact that the code is used as if it returns an object. However, any other return type would indicate that your code is supposed to return something at the end, which is also incorrect.
Constructor doesn’t return anything not even Void. Though some of the answers have mentioned that Constructor do return reference to the newly created object , which is not true. It’s the new operator that returns the object.
So Why constructor doesn’t return any value
Because its not supposed to return anything. The whole purpose of constructor is to initialize the current state of the object by setting the initial values.
So Why doesn’t it even return Void
This is actually a Design constraint which has been placed to distinguish it from methods. public void className() is perfectly legal in java but it denotes a method and not a constructor. To make the compiler understand that it’s a constructor , it requires a way to distinguish it.
all answers are biased towards C++/Java. there is no reason a constructor does not return a value other than the language design.
look at a constructor in a broader sense: it is a function which constructs a new object. you can write perfectly valid constructors in C:
typedef struct object object;
int object_create( object **this );
this is perfect OOP in C and the constructor returns value (this can also be called a factory, but the name depends on the intention).
however, in order to create an object automatically (to satisfy some type cast, or conversion for example), there have to be some rules defined. in C++, there is an argument-less constructor, which is inferred by the compiler if it is not defined.
the discussion is broader than what we think. Object Oriented Programming is a name which describes a way of thinking about programming. you can have OO in almost any language: all you need is structures and functions. mainstream languages like C++ and Java are so common that we think they define "the way". now look at the OO model in Ada: it is far from the model of C++ but is still OO. i am sure languages like Lisp have some other ways of doing OO.
One point that hasn't yet been discussed is that the constructor of class "foo" must be usable not only when creating instances of foo, but also when creating instances of classes derived from foo. In the absence of generics (which weren't available when Java, C++, or .net were designed) there would be no way for foo's constructor to return an object of any derived class. Therefore, what needs to happen is for the derived-class object to be created via some other means and then made available to foo's constructor (which will then be able to use the object in question as a foo when doing its initialization).
Even though the VM implementation of a constructor isn't to return any value, in practice it kind of does - the new object's reference. It would then be syntactically weird and / or confusing to be able to store one or both of the new object's reference and an additional return value in one statement.
So the reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the memory allocation and object initialization code in the runtime. Its return value (if it actually has one when compiled down to machine code) is opaque to the user - therefore, you can't specify it.
Constructor is not directly called by the user's code. It's called by the memory allocation and object initialization code in the run time. Its value is not visible to the user.
In case of C#, the syntax for declaring object is :
classname objectname= new constructor();
According to this line, if we are using assignment operator(=) then it should return some value. But the main objective of a constructor is to assign values to variables, so when we use a new keyword it creates instance of that class, and constructor assigns values to the variable for that particular instance of object, so constructor returns assigned values for that objects's instance.
We can not call constructors independently. Instead they are automatically called whenever objects are created.
Ex:
MyDate md = new Mydate(22,12,2012);
In above example new will return a memory location which will be held by md, and programatically we can not return multiple values in single statements.
So constructors can not return anything.
From what I know about OO design methodologies, I would say the following:
1)By allowing a constructor to return a value, framework developer would allow the program to crash in an instant where the returned value is not handled. To keep the integrity of the program workflow, not allowing a return value from the initialization of an object is a valid decision. Instead, language designer would suggest/force the coders to use getter/setter - access methods.
2)Allowing the object to return a value on initialization also opens possible information leaks. Specially when there are multiple layer or access modifications applied to the variables/methods.
As you aware that when object is created constructor will be automatically called So now imagine that constructor is returning an int value. So code should like this...
Class ABC
{
int i;
public:
int ABC()
{
i=0;
return i;
}
.......
};
int main()
{
int k= ABC abc; //constructor is called so we have to store the value return by it
....
}
But as you aware that stament like int k= ABC abc; is not possible in any programming language. Hope you can understand.
i found it helpful
This confusion arises from the assumption that constructors are just like any other functions/methods defined by the class. NO, they are not.
Constructors are just part of the process of object creation. They are not called like other member functions.
I would be using Java as my language in the answer.
class SayHelloOnCreation {
public SayHelloOnCreation() {
System.out.println("Hello, Thanks For Creating me!");
}
}
class Test {
public static void main(String[]args) {
SayHelloOnCreation thing = new SayHelloOnCreation(); //This line here, produces an output - Hello, Thanks For Creating me!
}
}
Now let us see what is happening here. in java, we use the new keyword to create an instance of a class. And as you can see in the code, in the line, SayHelloOnCreation thing = new SayHelloOnCreation();, the expression after the assignment operator runs before assignment is done. So using the keyword new, we call the constructor of that class (SayHelloOnCreation()) and this constructor creates an object on the Java Heap. After the object is created, a reference to that object is assigned to the thing reference of type SayHelloOnCreation.
The point that I am trying to keep here is that if constructors were allowed to have a return type, Firstly the strongly typed nature of the language would be compromised (Remember I am speaking about Java here).
Secondly, an object of class SayHelloOnCreation is created here so by default I guess the constructor returns a reference of the same type, to avoid ClassCastException.
A method returns the value to its caller method, when called explicitly. Since, a constructor is not called explicitly, who will it return the value to. The sole purpose of a constructor is to initialize the member variables of a class.
All Objects in actionscript3.0 inherit from the Object class, but the actionscript3.0 compiler seems not to be smart enough to understand this.
take a look at the following code:
package{
public class TestOne{
public function TestOne(){
var t2: TestTwo = new TestTwo();
trace(t2.toString()); // COMPILE TIME ERROR
trace((t2 as Object).toString(); // [object TestTwo]
var t22 : * = new TestTwo();
trace(t22.toString()); // [object TestTwo]
trace((t22 as Object).toString(); // [object TestTwo]
}
}
}
class TestTwo{}
t2.toString() gives a compile time error because the data type t2 does not include toString(). However, t2 does include toString() because it is an object as (t2 as Object).toString() shows. If we do not give the variable a datatype, like t22, then the problem is never encountered. Why cant the actionscript3.0 compiler relize that t2 is both TestTwo and Object?
This is because
Methods of the Object class are
dynamically created on Object's
prototype. To redefine this method in
a subclass of Object, do not use the
override keyword. For example, a
subclass of Object implements function
toString():String instead of using an
override of the base class.
So if you cast TestTwo to an Object, the compiler knows those methods will be implemented. If you don't cast it, TestTwo does not inherit those methods and so they have not been implemented and will error.
It's a bit of a weird one!
Class inheritance and prototype inheritance are two different things in AS3. Prototype inheritance is as far as I understand included for backwards compatibility with AS2/AS1, and it's prototype inheritance that's providing the toString() method on the variable that's cast to the Object class in your example. The Object prototype has the toString() method, not the Object class. Since the prototype is not present on your TestTwo class, it doesn't have a toString() method. If the toString() method was supplied via class inheritance instead, your example would compile.
So technically, your statement "All Objects in actionscript3.0 inherit from the Object class" is not entirely correct, because of the difference between prototype inheritance and class inheritance. Prototype inheritance is a somewhat esoteric OO concept found in script languages.
Does anyone know the reason why AS3 is designed like this?