suprasarcină dactilografiat constructor

voturi
216

Are cineva făcut supraîncărcării constructor dactilografiat. La pagina 64 din caietul de sarcini limba (v 0.8), există declarații care descriu suprasarcini constructor, dar nu a existat nici un cod de probă dată.

Am încercat o declarație de clasă într-adevăr de bază chiar acum; se pare ca acest lucru,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj: IBox) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   

    constructor() {
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
    }
}

Când a fugit cu BoxSample.ts TSC, aruncă-o definiție constructor duplicat - care este evidentă. Orice ajutor este apreciat.

Întrebat 03/10/2012 la 06:48
sursa de către utilizator
În alte limbi...                            


13 răspunsuri

voturi
190

Typescript vă permite să declare suprasarcini, dar puteți avea doar o singură implementare și că punerea în aplicare trebuie să aibă o semnătură, care este compatibil cu toate suprasarcini. În exemplul dvs., acest lucru poate fi ușor de realizat cu un parametru opțional ca în,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj?: IBox) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}

sau două suprasarcini cu un constructor mai general, ca in,

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox); 
    constructor(obj?: any) {    
        this.x = obj && obj.x || 0
        this.y = obj && obj.y || 0
        this.height = obj && obj.height || 0
        this.width = obj && obj.width || 0;
    }   
}
Publicat 03/10/2012 la 07:14
sursa de către utilizator

voturi
63

Rețineți că puteți lucra, de asemenea, în jurul valorii de lipsa de supraîncărcare la nivel de implementare, prin parametrii implicit dactilografiat, de exemplu:

interface IBox {    
    x : number;
    y : number;
    height : number;
    width : number;
}

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor(obj : IBox = {x:0,y:0, height:0, width:0}) {    
        this.x = obj.x;
        this.y = obj.y;
        this.height = obj.height;
        this.width = obj.width;
    }   
}

Edit: Ca de 05 decembrie '16, a se vedea răspunsul lui Benson pentru o soluție mai elaborată , care permite o mai mare flexibilitate.

Publicat 09/10/2012 la 07:29
sursa de către utilizator

voturi
48

In ceea ce priveste constructorul suprasarcini o alternativă ar fi să pună în aplicare suprasarcinilor suplimentare ca metode statice din fabrică . Cred că ei mai ușor de citit și mai puțin confuz decât testarea argumentele de apel. Aici este un exemplu simplu:

class Person {
    static fromData(data: PersonData) {
        let { first, last, birthday, gender = 'M' } = data 
        return new this(
            `${last}, ${first}`,
            calculateAge(birthday),
            gender
        )
    }

    constructor(
        public fullName: string,
        public age: number,
        public gender: 'M' | 'F'
    ) {}
}

interface PersonData {
    first: string
    last: string
    birthday: string
    gender?: 'M' | 'F'
}


let personA = new Person('Doe, John', 31, 'M')
let personB = Person.fromData({
    first: 'John',
    last: 'Doe',
    birthday: '10-09-1986'
})

Metoda Supraîncărcarea dactilografiat nu este real , să zicem, deoarece ar necesita prea mult cod generat de compilator și echipa de bază încearcă să evite ca , la toate costurile. În prezent , principalul motiv pentru metoda supraîncărcare să fie prezentă pe limba este de a oferi o modalitate de a scrie declarații pentru biblioteci cu argumente magice în API - ul lor. Din moment ce va trebui să faceți toate grele de ridicare de unul singur să se ocupe de seturi diferite de argumente eu nu văd mare avantaj în utilizarea suprasarcini în loc de metode separate.

Publicat 31/07/2016 la 21:08
sursa de către utilizator

voturi
38

Notă: acest lucru a fost simplificată și actualizată pentru a reflecta 4/13/2017 typescript 2.1, vezi istoricul pentru 1.8 typescript răspuns.

Se pare că doriți ca parametrul obiect să fie opțional și , de asemenea , fiecare dintre proprietățile în obiectul să fie opțională. În exemplu, astfel cum este prevăzut, nu este necesară sintaxa de suprasarcină. Am vrut să subliniez unele practici rele în unele dintre răspunsurile aici. Desigur, nu este cea mai mică expresie posibilă a scris în esență box = { x: 0, y: 87, width: 4, height: 0 }, dar acest lucru oferă toate cod subtilitățile sugerand faptul ca ai putea dori , eventual , din clasa așa cum este descris. Acest exemplu vă permite să apelați o funcție cu una, unele, toate, sau nici unul dintre parametrii și a obține în continuare valori implicite.

 /** @class */
 class Box {
     public x?: number;
     public y?: number;
     public height?: number;
     public width?: number;     

     // The class can work double-duty as the interface here since they are identical
     // Alternately, reference your own interface, e.g.:  `...BoxI = {} as BoxI` 
     constructor(obj: Box = {} as Box) {

         // Define the properties of the incoming `obj` object here. 
         // Setting a default value with the `= 0` syntax is optional for each parameter
         let {
             x = 0,
             y = 0,
             height = 0,
             width = 0
         } = obj;

         /** Use jsdoc comments here for inline ide auto-documentation */
         this.x = x;
         this.y = y;
         this.height = height;
         this.width = width;
     }
 }

Acesta este un mod foarte sigur de a scrie pentru parametrii care nu pot avea toate proprietățile obiectului definit. Acum puteți să scrie în siguranță oricare dintre acestea:

const box1 = new Box();
const box2 = new Box({});
const box3 = new Box({x:0});
const box4 = new Box({x:0, height:10});
const box5 = new Box({x:0, y:87,width:4,height:0});

 // Correctly reports error in TypeScript, and in js, box6.z is undefined
const box6 = new Box({z:0});  

Compilat, vezi că parametrii opționali cu adevărat sunt opționale, care să evite capcanele unei utilizate pe scară largă (dar predispuse la erori) sintaxa de rezervă var = isOptional || default;prin verificarea împotriva void 0, care este prescurtare pentru undefined:

Ieșirea Compilat

var Box = (function () {
    function Box(obj) {
        if (obj === void 0) { obj = {}; }
        var _a = obj.x, 
        x = _a === void 0 ? 1 : _a,
        _b = obj.y,
        y = _b === void 0 ? 1 : _b,
        _c = obj.height,
        height = _c === void 0 ? 1 : _c,
        _d = obj.width,
        width = _d === void 0 ? 1 : _d;
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
    return Box;
}());

Addendum: stabilirea unor valori implicite: mod greșit

||(Sau) operatorul

Luați în considerare pericolul ||/ sau operatori în stabilirea valorilor implicite alternative așa cum se arată în alte răspunsuri. Acest cod de mai jos ilustrează modul greșit de a seta valorile implicite. Puteți obține rezultate neașteptate atunci când se evaluează împotriva Falsey valori , cum ar fi 0, „“, nul, nedefinit, fals, NaN:

var myDesiredValue = 0;
var result = myDesiredValue || 2;

// This test will correctly report a problem with this setup.
console.assert(myDesiredValue === result && result === 0, 'Result should equal myDesiredValue. ' + myDesiredValue + ' does not equal ' + result);

Object.assign (aceasta, obj)

În testele mele, folosind dactilografiat destructurat obiect ES6 / poate fi aproape 90% mai repede decât Object.assign . Folosind un parametru destructurat permite doar metode și proprietăți care le - ați atribuit obiectului. De exemplu, ia în considerare această metodă:

class BoxTest {
    public x?: number = 1;

    constructor(obj: BoxTest = {} as BoxTest) {
        Object.assign(this, obj);
    }
}

Dacă un alt utilizator nu a fost folosind typescript și a încercat să plaseze un parametru care nu fac parte, să zicem, s - ar putea încerca punerea o zproprietate

var box = new BoxTest({x: 0, y: 87, width: 4, height: 0, z: 7});

// This test will correctly report an error with this setup. `z` was defined even though `z` is not an allowed property of obj.
console.assert(typeof box.z === 'undefined')
Publicat 05/12/2016 la 14:30
sursa de către utilizator

voturi
32

Știu că aceasta este o întrebare veche, dar noi în 1.4 este de tipuri de unire; folosi aceste pentru toate suprasarcini funcționale (inclusiv constructori). Exemplu:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);
Publicat 04/02/2015 la 18:28
sursa de către utilizator

voturi
20

Actualizare (08 iunie 2017): guyarad și snolflake face puncte valabile în observațiile de mai jos pentru răspunsul meu. Mi - ar recomanda cititorilor uita la răspunsurile pe Benson , Joe și snolflake care au răspunsuri mai bune decât a mea.

Răspuns original (27 ianuarie 2014)

Un alt exemplu de modul de a realiza constructor supraîncărcării:

class DateHour {

  private date: Date;
  private relativeHour: number;

  constructor(year: number, month: number, day: number, relativeHour: number);
  constructor(date: Date, relativeHour: number);
  constructor(dateOrYear: any, monthOrRelativeHour: number, day?: number, relativeHour?: number) {
    if (typeof dateOrYear === "number") {
      this.date = new Date(dateOrYear, monthOrRelativeHour, day);
      this.relativeHour = relativeHour;
    } else {
      var date = <Date> dateOrYear;
      this.date = new Date(date.getFullYear(), date.getMonth(), date.getDate());
      this.relativeHour = monthOrRelativeHour;
    }
  }
}

Sursa: http://mimosite.com/blog/post/2013/04/08/Overloading-in-TypeScript

Publicat 27/01/2014 la 17:02
sursa de către utilizator

voturi
3

În cazul în care un parametru opțional, tastat este suficient de bun, luați în considerare următorul cod care realizează același lucru fără a repeta proprietățile sau de a defini o interfață:

export class Track {
   public title: string;
   public artist: string;
   public lyrics: string;

   constructor(track?: Track) {
     Object.assign(this, track);
   }
}

Rețineți acest lucru se va atribui toate proprietățile în trecut track, ajunul dacă nu sunt definite pe Track.

Publicat 06/11/2016 la 00:22
sursa de către utilizator

voturi
1

Puteți ocupa de acest lucru prin:

import { assign } from 'lodash'; // if you don't have lodash use Object.assign
class Box {
    x: number;
    y: number;
    height: number;
    width: number;
    constructor(obj: Partial<Box> = {}) {    
         assign(this, obj);
    }
}

Parțial va face câmpurile (x, y, înălțime, lățime) optionalele, permițând mai multor constructori

de exemplu: puteți face new Box({x,y})fără înălțime și lățime.

= {}Se va ocupa de valoare falsy , cum ar fi nedefinite , etc, null, și apoi poți să facinew Box()

Publicat 11/09/2018 la 09:36
sursa de către utilizator

voturi
1

O altă versiune ca la @ ShinNoNoir lui cod, utilizând valori implicite și sintaxă răspândirea:

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor({x, y, height, width}: IBox = { x: 0, y: 0, height: 0, width: 0 }) {
        this.x = x;
        this.y = y;
        this.height = height;
        this.width = width;
    }
}
Publicat 30/11/2016 la 05:11
sursa de către utilizator

voturi
0

Eu folosesc următoarea alternativă pentru a obține default / params opționale și „tip-de-supraîncărcat“ constructori cu număr variabil de params:

private x?: number;
private y?: number;

constructor({x = 10, y}: {x?: number, y?: number}) {
 this.x = x;
 this.y = y;
}

Știu că nu e cel mai frumos cod vreodată, dar se obișnuiește. Nu este nevoie de interfață suplimentară și permite membrilor privați, care nu este posibilă la utilizarea interfeței.

Publicat 20/09/2019 la 14:28
sursa de către utilizator

voturi
0

De fapt, ar putea fi prea târziu pentru acest răspuns, dar puteți face acum acest lucru:

class Box {
    public x: number;
    public y: number;
    public height: number;
    public width: number;

    constructor();
    constructor(obj: IBox);
    constructor(obj?: IBox) {    
        this.x = !obj ? 0 : obj.x;
        this.y = !obj ? 0 : obj.y;
        this.height = !obj ? 0 : obj.height;
        this.width = !obj ? 0 : obj.width;
    }
}

astfel încât în ​​loc de metode statice puteți face cele de mai sus. Sper că vă va ajuta !!!

Publicat 26/05/2019 la 23:31
sursa de către utilizator

voturi
0

Putem simula suprasarcina constructor cu ajutorul polițiștilor

interface IUser {
  name: string;
  lastName: string;
}

interface IUserRaw {
  UserName: string;
  UserLastName: string;
}

function isUserRaw(user): user is IUserRaw {
  return !!(user.UserName && user.UserLastName);
}

class User {
  name: string;
  lastName: string;

  constructor(data: IUser | IUserRaw) {
    if (isUserRaw(data)) {
      this.name = data.UserName;
      this.lastName = data.UserLastName;
    } else {
      this.name = data.name;
      this.lastName = data.lastName;
    }
  }
}

const user  = new User({ name: "Jhon", lastName: "Doe" })
const user2 = new User({ UserName: "Jhon", UserLastName: "Doe" })
Publicat 27/03/2019 la 00:18
sursa de către utilizator

voturi
0

Ar trebui avut în vedere faptul că ...

contructor ()

constructor (a: orice, b: orice, c: orice)

Este la fel de

nou () sau noi ( "a", "b", "c")

Prin urmare

constructor (a: orice, b: orice, c: orice) este aceeași de mai sus și este mai flexibilă ...

nou () sau noi ( "a") sau noi ( "a", "b") sau noi ( "a", "b", "c")

Publicat 02/06/2018 la 14:15
sursa de către utilizator

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more