Написание получателя общего типа объединения

Как было сказано ранее, экземпляры String неизменяемы. StringBuffer и StringBuilder являются изменяемыми и подходят для этой цели, нужно ли вам быть потокобезопасными или нет.

Однако есть способ изменить строку, но я бы никогда не рекомендовал ее, потому что это небезопасный, ненадежный и его можно считать обманом: вы можете использовать отражение для изменения внутреннего массива char, содержащего объект String. Reflection позволяет вам получать доступ к полям и методам, которые обычно скрыты в текущей области (частные методы или поля из другого класса ...).

public static void main(String[] args) {
    String text = "This is a test";
    try {
        //String.value is the array of char (char[])
        //that contains the text of the String
        Field valueField = String.class.getDeclaredField("value");
        //String.value is a private variable so it must be set as accessible 
        //to read and/or to modify its value
        valueField.setAccessible(true);
        //now we get the array the String instance is actually using
        char[] value = (char[])valueField.get(text);
        //The 13rd character is the "s" of the word "Test"
        value[12]='x';
        //We display the string which should be "This is a text"
        System.out.println(text);
    } catch (NoSuchFieldException | SecurityException e) {
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

0
задан DrPhil 13 July 2018 в 17:11
поделиться

2 ответа

Типы TypeScript существуют только во время компиляции (поскольку Javascript не имеет понятия типов).

Поэтому вы не можете использовать параметры типа во время выполнения.

Вместо этого вы может проверить if (either instanceof backup.constructor), что является простым способом получить конструктор A во время выполнения.

Обратите внимание, что это не будет работать для примитивов.

1
ответ дан SLaks 17 August 2018 в 12:21
поделиться
  • 1
    Не будет работать и для объектных литералов, набранных с помощью интерфейсов. – William Lohan 13 July 2018 в 17:53

Поскольку https://stackoverflow.com/a/51329983/6656422 указывает, что во время выполнения во время выполнения нет типов TypeScript. Вы должны проверить «тип». Чтобы сделать что-то общее, вы можете пройти в тесте.

function getLeftOrDefault<A, B>(either: A | B, backup: A, isA: (obj: any) => obj is A): A {
  if (isA(either)) {
    return either;
  }
  return backup;
}

Использование:

Много раз интерфейсы используются для строго типизирующих объектных литералов, вы можете проверить свойство (ы).

interface Car {
  engine: string;
}

interface Tree {
  branches: any[];
}

function isCar(obj: any): obj is Car {
  return !!obj.engine;
}

const myCar: Car = { engine: '350' };
const myTree: Tree = { branches: [] };
const myBackup: Car = { engine: '396' };

getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '350' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }

Если ваши типы являются классами, у них есть конструкторы во время выполнения.

class Car {
  constructor(public engine: string) {}
}

class Tree {
  constructor(public branches: any[]) {}
}

function isCar(obj: any): obj is Car {
  return obj instanceof Car;
}

const myCar: Car = new Car('350');
const myTree: Tree = new Tree([]);
const myBackup: Car = new Car('396');

getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '350' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }

Однако проверка конструктора не является доказательством дурака из-за литья

const myCar: Car = { engine: '350' };
const myTree: Tree = { branches: [] };
const myBackup: Car = { engine: '396' };

getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '396' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }
1
ответ дан William Lohan 17 August 2018 в 12:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: