Constructor overbelastning i Loggfila

stemmer
242

Har noen gjort konstruktør overbelastning i Loggfila. På side 64 i den språkspesifikasjonen (v 0.8), er det utsagn som beskriver konstruktøroverbelastninger, men det var ikke noen eksempelkode gitt.

Jeg prøver ut en veldig grunnleggende klasse erklæring akkurat nå; det ser ut som dette,

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;
    }
}

Når drev med TSC BoxSample.ts, kaster det ut en kopi konstruktør definisjon - som er åpenbare. Alle hjelpe er verdsatt.

Publisert på 03/10/2012 klokken 05:48
kilden bruker
På andre språk...                            


13 svar

stemmer
203

Loggfila lar deg erklære overbelastning, men du kan bare ha en implementering og at gjennomføringen må ha en signatur som er kompatibel med alle overbelastning. I ditt eksempel, kan dette enkelt gjøres med en valgfri parameter som i,

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;
    }   
}

eller to overbelastninger med en mer generell konstruktør som i,

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;
    }   
}
Svarte 03/10/2012 kl. 06:14
kilden bruker

stemmer
68

Merk at du også kan omgå mangelen på overbelastning på gjennomføringen nivå gjennom standard parametere i maskinskrevet manuskript, f.eks:

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: Fra 5 desember '16, se Benson svar for en mer forseggjort løsning som gir mer fleksibilitet.

Svarte 09/10/2012 kl. 06:29
kilden bruker

stemmer
54

Angående konstruktør overbelaster en alternativ vil være å implementere tilleggsbelastninger som statiske fabrikk metoder . Jeg tror det er mer lesbar og mindre forvirrende enn å teste dine samtale argumenter. Her er et enkelt eksempel:

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'
})

Metode overbelastning i Loggfila er ikke på ordentlig , la oss si, da det ville kreve for mye kompilator-generert kode og kjerneteamet prøve å unngå at alle kostnader. I dag den viktigste årsaken til metoden overbelastning å være til stede på språket er å gi en måte å skrive erklæringer for biblioteker med magiske argumenter i sin API. Siden du trenger å gjøre alle de tunge løftene selv å håndtere ulike sett med argumenter jeg ser ikke mye nytte i å bruke overbelastning i stedet for skilt metoder.

Svarte 31/07/2016 kl. 21:08
kilden bruker

stemmer
48

Merk: Dette ble forenklet og oppdatert 4/13/2017 å reflektere Loggfila 2.1, se historikk for Loggfila 1,8 svaret.

Det høres ut som du vil at objektet parameter å være valgfritt, og også hver av eiendommene i objektet skal være valgfritt. I eksemplet, som forutsatt, overbelastning syntaks er ikke nødvendig. Jeg ønsket å peke ut noen dårlige praksis i noen av svarene her. Gitt, det er ikke den minste mulige uttrykk for i hovedsak å skrive box = { x: 0, y: 87, width: 4, height: 0 }, men dette gir alle kode hinte niceties du kunne ønske fra klassen som beskrevet. Dette eksempelet kan du kalle en funksjon med en, noen, alle, eller ingen av parametrene og likevel få standardverdier.

 /** @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;
     }
 }

Dette er en svært sikker måte å skrive for parametere som kanskje ikke har alle egenskapene til objektet definert. Du kan nå trygt skrive noen av disse:

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});  

Kompilert, ser du at de valgfrie parametere virkelig er valgfrie, som unngår fallgrubene en mye brukt (men feilutsatte) reservesyntaksen var = isOptional || default;ved å sjekke mot void 0, som er forkortelse for undefined:

Den kompilerte Output

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;
}());

Tillegg: Innstilling standardverdier: feil vei

Den ||(eller) operatør

Vurdere faren for ||/ eller operatører når du setter standardreserveverdier som vist i noen andre svar. Denne koden nedenfor illustrerer feil måte å angi standardinnstillinger. Du kan få uventede resultater ved evaluering mot falsey verdier som 0, '', null, udefinert, falsk, 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 (dette, obj)

I mine tester, ved hjelp ES6 / Loggfila destrukturisert objekt kan være nesten 90% raskere enn Object.assign . Ved hjelp av en destrukturerte parameter bare tillater metoder og egenskaper du har tilordnet objektet. For eksempel vurdere denne metoden:

class BoxTest {
    public x?: number = 1;

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

Hvis en annen bruker ikke brukte Loggfila og forsøkte å plassere en parameter som ikke hører hjemme, sier, kan de prøve å sette en zeiendom

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')
Svarte 05/12/2016 kl. 14:30
kilden bruker

stemmer
32

Jeg vet dette er en gammel spørsmålet, men nytt i 1.4 er fagforenings typer; bruke disse for alle funksjonsbelastninger (inkludert konstruktører). Eksempel:

class foo {
    private _name: any;
    constructor(name: string | number) {
        this._name = name;
    }
}
var f1 = new foo("bar");
var f2 = new foo(1);
Svarte 04/02/2015 kl. 18:28
kilden bruker

stemmer
19

Update (08.06.2017): guyarad og snolflake fatte gyldige punkter i sine kommentarer under mitt svar. Jeg vil anbefale leserne ser på svarene fra Benson , Joe og snolflake som har bedre svar enn mine.

Original svar (27.01.2014)

Et annet eksempel på hvordan man skal oppnå konstruktør overbelastning:

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;
    }
  }
}

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

Svarte 27/01/2014 kl. 16:02
kilden bruker

stemmer
3

I det tilfelle hvor en valgfri, skrevet parameter er god nok, vurdere den følgende kode som gir samme resultat uten å gjenta egenskapene eller avgrenses en grenseflate:

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

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

Husk dette vil tildele alle eiendommer vedtatt i track, like før hvis de ikke er definert på Track.

Svarte 06/11/2016 kl. 00:22
kilden bruker

stemmer
1

Du kan håndtere dette ved å:

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);
    }
}

Delvis vil gjøre felt (x, y, høyde, bredde) optionals, slik at flere konstruktører

f.eks: du kan gjøre new Box({x,y})uten høyde og bredde.

Den = {}vil håndtere falsy verdi som udefinert, null etc, og deretter kan du gjørenew Box()

Svarte 11/09/2018 kl. 09:36
kilden bruker

stemmer
1

En annen versjon som til @ ShinNoNoir kode, ved hjelp av standardverdier og spredning syntaks:

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;
    }
}
Svarte 30/11/2016 kl. 05:11
kilden bruker

stemmer
0

Jeg bruker følgende alternativ for å få standard / valgfrie parametere og "kind-of-overbelastet" konstruktører med variabelt antall params:

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

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

Jeg vet det ikke er den peneste kode noensinne, men en blir vant til det. Ingen behov for ekstra Interface og det gjør at private medlemmer, som ikke er mulig da bruker grensesnitt.

Svarte 20/09/2019 kl. 14:28
kilden bruker

stemmer
0

Egentlig kan det være for sent for dette svaret, men du kan nå gjøre dette:

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;
    }
}

så i stedet for statiske metoder kan du gjøre det over. Jeg håper det vil hjelpe deg !!!

Svarte 26/05/2019 kl. 23:31
kilden bruker

stemmer
0

Vi kan simulere konstruktør overbelastning ved hjelp av vakter

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" })
Svarte 27/03/2019 kl. 00:18
kilden bruker

stemmer
-3

Du bør hadde i tankene at ...

contructor()

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

Det er det samme som new()ellernew("a","b","c")

Og dermed

constructor(a?:any, b?:any, c?:any)

er den samme ovenfor, og er mer fleksibel ...

new()eller new("a")eller new("a","b")ellernew("a","b","c")

Svarte 02/06/2018 kl. 14:15
kilden bruker

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