How can I replicate multiple primary constructors? - constructor

I'm not sure what Kotlin best practice is in this area.
Say I have a Java class, User that has two fields: username and password. It has a primary constructor like this:
public User(String username, String password) {
this.username = username;
this.password = hashPassword(password);
}
and a second constructor for the ORM:
public User(String username, String password) {
this.username = username;
this.password = password;
}
(plus lots more fields not shown)
With this setup, I can present a friendly face to most of the code, and still let the ORM pass all the fields in to recreate the object from the database.
My Kotlin code has a primary constructor as such:
class User(var username: String,
var name: String,
password: String)
with an initializer that calls hashPassword and assigns it to a private property.
How can I construct a secondary constructor properly, such that I don't have to hash the value coming out of the database?

(plus lots more fields not shown)
By assuming that this means you second constructor has a different signature, e.g. by adding another field to its parameter list, what you want can be achieved several ways:
Create a private primary constructor and several secondary constructors:
class User
private constructor(val username : String)
{
private val password : String
constructor(username : String, password : String)
: this(username)
{
this.password = hashPassword(password)
}
constructor(username : String, password : String, anotherParameter : String)
: this(username)
{
this.password = password
}
}
Make password a var and assign the password again after calling the primary constructor (Please note that this requires Kotlin 1.2 or later):
class User(val username : String, password : String)
{
private lateinit var password : String
init
{
if (!this::password.isInitialized)
this.password = hashPassword(password)
}
constructor(username : String, password : String, anotherParameter : String)
: this(username, password)
{
this.password = password
}
}
Add a flag to the primary constructor that tells whether the password was already hashed
class User(val username : String, password : String, isHashed : Boolean = false)
{
private val password : String
init
{
this.password = if (isHashed) password else hashPassword(password)
}
constructor(username : String, password : String, anotherParameter : String)
: this(username, password, isHashed=true)
}

Related

In kotlin, how to make the setter of properties in primary constructor private?

In kotlin, how to make the setter of properties in primary constructor private?
class City(val id: String, var name: String, var description: String = "") {
fun update(name: String, description: String? = "") {
this.name = name
this.description = description ?: this.description
}
}
I want the setter of properties name to be private, and the getter of it public, how can I do?
The solution is to create a property outside of constructor and set setter's visibility.
class Sample(var id: Int, name: String) {
var name: String = name
private set
}
Update:
They're discussing it here: https://discuss.kotlinlang.org/t/private-setter-for-var-in-primary-constructor/3640
You can try like this
class Sample(var id: Int, private var name:String) {
// Backing field
var _name: String = ""
get() = name
private set
}
fun main(args: Array<String>) {
println("Hello World")
val sample = Sample(1, "hello")
// println(sample.name); It's not possible
println(sample._name)
}

springMVC can't receive full json data

I'm trying to use $.ajax and #RequestBody, but when I use it to pass Integer type. It can't read the data and print null. What kind of data #RequestBody can receive?
Here is my code:
var user = {
"username" : "test",
"password" : "test",
"age" : 1
};
$.ajax({
url: "/test1",
type: "POST",
data: JSON.stringify(user),
contentType:"application/json; charset=utf-8",
success: function() {
alert("success")
}
})
and this is my controller:
#RequestMapping(value = "/test1")
public String test2(#RequestBody User user) {
//Can't receive the Param.
// console result : null
System.out.println(user.getAge());
//Nothing wrong
//console result:
// username: test
// password: test
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return "test";
}
Here is User class:
public class User {
private Integer age;
private String username;
private String password;
//Setting and Getting
}
I found where the issue is. In User class:
public class User {
//It should be `int`
private Integer age;
}
int is a base data type. Integer is a wrapper class. I need to transform data type.

How to get JSON Object, REST API, Jhipster, SpringBoot

I'm coding an API using Jhipster. Server side is programmed with Spring-Boot. I want to get JSON Object that i send with PostMan
{
"user" : {
"name" : "name",
"surname": "surname"
}
}
I create a ressource and a class to get this JSON Object
#RequestMapping(value = "/",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<AlertBalance> create(#RequestBody User user) throws URISyntaxException {
System.out.println("name "+ user.getName()+"/ surname : "+User.getSurname());
}
User class Code
#JsonIgnoreProperties(ignoreUnknown = true)
public class User implements Serializable {
private String name;
private String surname ;
#JsonCreator
public User(#JsonProperty("surname") String surname , #JsonProperty("name") String name){
this.surname = surname;
this.name = name;
}
public User(){
}
//setters and getters
}
The create() method is called when I do request from postman, but the value of name and surname is null. Do you know what I can do to get the real values ?
I just find the mistake, the JSON Object I sent was incompatible. I change it with
{
"name" : "name",
"surname": "surname"
}
and now it works.

TypeScript Constructor Overload with Empty Constructor

Why is it not allowed to have separate constructor definitions in TypeScript?
To have e.g. two constructors, I need to write my code like this.
constructor(id: number)
constructor(id: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Thereby I need to put ? after the parameters that are not required in the first constructor.
Why can't I write it like this?
constructor(id: number) {
this.id = id;
}
constructor(id: number, name: string, surname: string, email: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
So that for both constructors all parameters are mandatory.
Moreover, if I need to have an empty constructor things get even weirder, since I need to mark every parameter with a ?.
constructor()
constructor(id?: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Why does TypeScript differs from common languages like C# or Python here?
I would expect it to work like this.
constructor() {
}
constructor(id: number, name: string, surname: string, email: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
So you can pass none parameter or must pass all parameters.
Because your constructor implementation is called by all your overload constructors. (Technically, at runtime there's only one constructor function that gets called with the various overload argument signatures.)
Imagine it like this:
overload_constructor(id:string) {
implementation_constructor(id);
}
implementation_constructor(id:string, name?:string, age?:number) {
// ...
}
Thinking of it this way, overload_constructor could not call implementation_constructor unless name and age are optional.
Also see Basarat's answer, the implementation isn't exposed for public usage by the type checker (though at runtime it's the "real" constructor used in JS). If you want to only allow (), (id), or (id, name, surname, email) as the only valid call signatures you would do it like this:
constructor()
constructor(id: number)
constructor(id: number, name: string, surname: string, email: string)
constructor(id?: number, name?: string, surname?: string, email?: string) {
this.id = id;
this.name = name;
this.surname = surname;
this.email = email;
}
Note that in the implementation all parameters are optional, but that signature is not exposed when compiling and you can only use these these calls:
new Foo()
new Foo(1)
new Foo(1, "a", "b", "c")
Not, for example:
new Foo(1, "a")
The last function overload is only used in the implementation and not available publicly. This is shown below:
class Foo{
constructor()
constructor(id?: number) {
}
}
const foo1 = new Foo();
const foo2 = new Foo(123); // Error! : not public
If you want id:number to be available publically ofcourse you can add another overload:
class Foo{
constructor()
constructor(id: number)
constructor(id?: number) {
}
}
const foo1 = new Foo();
const foo2 = new Foo(123); // Okay
const foo3 = new Foo('hello'); // Error: Does not match any public overload
The reason is that TypeScript tries not to do fancy code generation for function overloading (traditional languages do this using name mangling e.g. C++)
So you can pass none parameter or must pass parameters.
Actually you can make the final overload optional but none of the public ones as optional. Consider the following example:
class Foo{
constructor(id: number, name:string)
constructor(name:string)
constructor(idOrName?: number|string, name?:string) {
}
}
const foo1 = new Foo('name'); // Okay
const foo2 = new Foo(123); // Error: you must provide a name if you use the id overload
const foo3 = new Foo(123,'name'); // Okay
You can use Builder pattern to solve this. Even in C# or Python, it quickly becomes a better approach as the number of constructor arguments grows.
class Foo {
constructor(public id: number, public name: string, public surname: string, public email: string) {
}
static Builder = class {
id: number = NaN;
name: string = null;
surname: string = null;
email: string = null;
Builder() {
}
build(): Foo {
return new Foo(this.id, this.name, this.surname, this.email);
}
}
}
If you use static methods to implement overload contructors, see.
export class User implements IUser {
constructor(
private _id: string,
private _name: string,
private _email: string,
) {}
static New(jsonUser:string){
return new User(
JSON.parse(jsonUser).id,
JSON.parse(jsonUser).name,
JSON.parse(jsonUser).email)
}
}

F#: How to apply Json.NET [JsonConstructor] attribute to primary constructor?

I'm trying to do something in F# like the JsonConstructorAttribute example in the Json.NET documentation:
public class User
{
public string UserName { get; private set; }
public bool Enabled { get; private set; }
public User()
{
}
[JsonConstructor]
public User(string userName, bool enabled)
{
UserName = userName;
Enabled = enabled;
}
}
The analog in F# appears to be something like the following, but I'm getting an error on the placement of [<JsonConstructor>]:
[<JsonConstructor>] // ERROR! (see below)
type User (userName : string, enabled : bool) =
member this.UserName = userName
member this.Enabled = enabled
The error is
This attribute is not valid for use on this language element
So then, how do I decorate the primary constructor with [<JsonConstructor>]?
It turns out that it's pretty easy. Target the primary constructor by placing [<JsonConstructor>] just before the primary constructor's parameter list:
type User [<JsonConstructor>] (userName : string, enabled : bool) =
member this.UserName = userName
member this.Enabled = enabled