Как просмотреть все свойства данного объекта JS?

takeWhile работает нормально, вам понадобится что-то вроде этого:

const stream = interval(1000)   
  .pipe(
     takeWhile(() => messages.length > 0),
     map(() => messages.pop()),   
  );

Я сделал небольшой пример на stackblitz, надеюсь, вы можете использовать это в своем приложении: https: // stackblitz .com / редактировать / машинопись-sq6wxb? файл = index.ts

24
задан River 18 October 2017 в 03:03
поделиться

8 ответов

Престижность при обучении на практике. Вот предложения о «возможностях» для улучшения:

  1. Может существовать только один тип кортежей (если установлена ​​блокировка типа). Это ухудшает возможности повторного использования и масштабируемости в программах, желающих использовать несколько типов кортежей, если только вы не прибегаете к повторному использованию «вырезать и вставить» (BirthdayTuple, DimensionsTuple, StreetAddressTuple, ...). Рассмотрим класс TupleFactory, который принимает целевые типы и создает объект конструктора кортежей для генерации кортежей.

  2. Допустимость «null» как значения в кортеже не задокументирована. Я думаю, что до того, как Typelock установлен, null разрешен; но после установки Typelock код сгенерирует исключение NullPointerException - это противоречиво. Если они не разрешены, конструктор должен их перехватить и запретить (независимо от Typelock). Если они разрешены, тогда код в целом (конструктор, равно, хэш-код и т. Д.) Нуждается в модификации, чтобы сделать это возможным.

  3. Решите, должны ли кортежи быть объектами неизменных значений. На основании отсутствия методов установки, я бы предположил, что так. Если это так, то будьте осторожны с «принятием» входящего массива - lastTuple=this.arr. Несмотря на то, что это конструктор var arg, конструктор может быть вызван напрямую с массивом. Класс принимает массив (сохраняет ссылку на него), и значения в массиве могут быть впоследствии изменены вне класса. Я сделал бы мелкую копию массива, но также задокументировал бы потенциальную проблему с кортежами с неизменяемыми значениями (которые могли быть изменены вне кортежей).

  4. В вашем методе equals отсутствует проверка нуля (if (obj == null) return false) и проверка класса (либо obj instanceof Tuple, либо this.getClass().equals(object.getClass())). Идиома равенства одинаково хорошо документирована.

  5. Нет способа просмотреть значения кортежа, кроме как через toString. Это защищает ценности и общую неизменность, но я думаю, что это ограничивает полезность класса.

  6. Хотя я понимаю, что это всего лишь пример, я не ожидал бы использовать этот класс для чего-то вроде дней рождения / дат. В доменах решений с фиксированными типами объектов реальные классы (например, Date) намного лучше. Я хотел бы представить этот класс полезным в определенных областях, где кортежи являются объектами первого класса.

Редактировать Думаю об этом. Вот мой взгляд на некоторый код (на github + tests ):

===
Tuple.java
===
package com.stackoverflow.tuple;

/**
 * Tuple are immutable objects.  Tuples should contain only immutable objects or
 * objects that won't be modified while part of a tuple.
 */
public interface Tuple {

    public TupleType getType();
    public int size();
    public <T> T getNthValue(int i);

}


===
TupleType.java
===
package com.stackoverflow.tuple;

/**
 * Represents a type of tuple.  Used to define a type of tuple and then
 * create tuples of that type.
 */
public interface TupleType {

    public int size();

    public Class<?> getNthType(int i);

    /**
     * Tuple are immutable objects.  Tuples should contain only immutable objects or
     * objects that won't be modified while part of a tuple.
     *
     * @param values
     * @return Tuple with the given values
     * @throws IllegalArgumentException if the wrong # of arguments or incompatible tuple values are provided
     */
    public Tuple createTuple(Object... values);

    public class DefaultFactory {
        public static TupleType create(final Class<?>... types) {
            return new TupleTypeImpl(types);
        }
    }

}


===
TupleImpl.java (not visible outside package)
===
package com.stackoverflow.tuple;

import java.util.Arrays;

class TupleImpl implements Tuple {

    private final TupleType type;
    private final Object[] values;

    TupleImpl(TupleType type, Object[] values) {
        this.type = type;
        if (values == null || values.length == 0) {
            this.values = new Object[0];
        } else {
            this.values = new Object[values.length];
            System.arraycopy(values, 0, this.values, 0, values.length);
        }
    }

    @Override
    public TupleType getType() {
        return type;
    }

    @Override
    public int size() {
        return values.length;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getNthValue(int i) {
        return (T) values[i];
    }

    @Override
    public boolean equals(Object object) {
        if (object == null)   return false;
        if (this == object)   return true;

        if (! (object instanceof Tuple))   return false;

        final Tuple other = (Tuple) object;
        if (other.size() != size())   return false;

        final int size = size();
        for (int i = 0; i < size; i++) {
            final Object thisNthValue = getNthValue(i);
            final Object otherNthValue = other.getNthValue(i);
            if ((thisNthValue == null && otherNthValue != null) ||
                    (thisNthValue != null && ! thisNthValue.equals(otherNthValue))) {
                return false;
            }
        }

        return true;
    }

    @Override
    public int hashCode() {
        int hash = 17;
        for (Object value : values) {
            if (value != null) {
                hash = hash * 37 + value.hashCode();
            }
        }
        return hash;
    }

    @Override
    public String toString() {
        return Arrays.toString(values);
    }
}


===
TupleTypeImpl.java (not visible outside package)
===
package com.stackoverflow.tuple;

class TupleTypeImpl implements TupleType {

    final Class<?>[] types;

    TupleTypeImpl(Class<?>[] types) {
        this.types = (types != null ? types : new Class<?>[0]);
    }

    public int size() {
        return types.length;
    }

    //WRONG
    //public <T> Class<T> getNthType(int i)

    //RIGHT - thanks Emil
    public Class<?> getNthType(int i) {
        return types[i];
    }

    public Tuple createTuple(Object... values) {
        if ((values == null && types.length == 0) ||
                (values != null && values.length != types.length)) {
            throw new IllegalArgumentException(
                    "Expected "+types.length+" values, not "+
                    (values == null ? "(null)" : values.length) + " values");
        }

        if (values != null) {
            for (int i = 0; i < types.length; i++) {
                final Class<?> nthType = types[i];
                final Object nthValue = values[i];
                if (nthValue != null && ! nthType.isAssignableFrom(nthValue.getClass())) {
                    throw new IllegalArgumentException(
                            "Expected value #"+i+" ('"+
                            nthValue+"') of new Tuple to be "+
                            nthType+", not " +
                            (nthValue != null ? nthValue.getClass() : "(null type)"));
                }
            }
        }

        return new TupleImpl(this, values);
    }
}


===
TupleExample.java
===
package com.stackoverflow.tupleexample;

import com.stackoverflow.tuple.Tuple;
import com.stackoverflow.tuple.TupleType;

public class TupleExample {

    public static void main(String[] args) {

        // This code probably should be part of a suite of unit tests
        // instead of part of this a sample program

        final TupleType tripletTupleType =
            TupleType.DefaultFactory.create(
                    Number.class,
                    String.class,
                    Character.class);

        final Tuple t1 = tripletTupleType.createTuple(1, "one", 'a');
        final Tuple t2 = tripletTupleType.createTuple(2l, "two", 'b');
        final Tuple t3 = tripletTupleType.createTuple(3f, "three", 'c');
        final Tuple tnull = tripletTupleType.createTuple(null, "(null)", null);
        System.out.println("t1 = " + t1);
        System.out.println("t2 = " + t2);
        System.out.println("t3 = " + t3);
        System.out.println("tnull = " + tnull);

        final TupleType emptyTupleType =
            TupleType.DefaultFactory.create();

        final Tuple tempty = emptyTupleType.createTuple();
        System.out.println("\ntempty = " + tempty);

        // Should cause an error
        System.out.println("\nCreating tuple with wrong types: ");
        try {
            final Tuple terror = tripletTupleType.createTuple(1, 2, 3);
            System.out.println("Creating this tuple should have failed: "+terror);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace(System.out);
        }

        // Should cause an error
        System.out.println("\nCreating tuple with wrong # of arguments: ");
        try {
            final Tuple terror = emptyTupleType.createTuple(1);
            System.out.println("Creating this tuple should have failed: "+terror);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace(System.out);
        }

        // Should cause an error
        System.out.println("\nGetting value as wrong type: ");
        try {
            final Tuple t9 = tripletTupleType.createTuple(9, "nine", 'i');
            final String verror = t9.getNthValue(0);
            System.out.println("Getting this value should have failed: "+verror);
        } catch (ClassCastException ex) {
            ex.printStackTrace(System.out);
        }

    }

}

===
Sample Run
===
t1 = [1, one, a]
t2 = [2, two, b]
t3 = [3.0, three, c]
tnull = [null, (null), null]

tempty = []

Creating tuple with wrong types: 
java.lang.IllegalArgumentException: Expected value #1 ('2') of new Tuple to be class java.lang.String, not class java.lang.Integer
    at com.stackoverflow.tuple.TupleTypeImpl.createTuple(TupleTypeImpl.java:32)
    at com.stackoverflow.tupleexample.TupleExample.main(TupleExample.java:37)

Creating tuple with wrong # of arguments: 
java.lang.IllegalArgumentException: Expected 0 values, not 1 values
    at com.stackoverflow.tuple.TupleTypeImpl.createTuple(TupleTypeImpl.java:22)
    at com.stackoverflow.tupleexample.TupleExample.main(TupleExample.java:46)

Getting value as wrong type: 
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
    at com.stackoverflow.tupleexample.TupleExample.main(TupleExample.java:58)
47
ответ дан 28 November 2019 в 22:33
поделиться

Как это безопасно? Вы генерируете исключения времени выполнения вместо сообщения об ошибках типа во время компиляции.

Вы пытаетесь абстрагироваться от арности, которая (на данный момент) невозможна в статически типизированных языках, без потери безопасности типов.

Приложение:

Кортежи могут состоять из разнородных элементов (то есть элементов с различными типами). Поэтому обеспечение даже «безопасности типов rutime» для этого класса Tuple невозможно. Клиенты класса несут ответственность за выполнение соответствующих бросков.

Это лучшее, что вы можете сделать в Java: ( Редактировать: См. пост Брента для лучшей реализации Tuple. (Это не не требует типов на стороне клиента.))

final class Tuple {
  private final List<Object> elements;

  public Tuple(final Object ... elements) {
    this.elements = Arrays.asList(elements);
  }

  @Override
  public String toString() {
    return elements.toString();
  }

  //
  // Override 'equals' and 'hashcode' here
  //

  public Object at(final int index) {
    return elements.get(index);
  }
}
11
ответ дан 28 November 2019 в 22:33
поделиться

Это самое простое и лучшее решение. Это похоже на то, как кортежи представлены в .NET. Это тщательно обходит стирание Java. Это сильно типизировано. Это не бросает исключения. Он очень прост в использовании.

public interface Tuple
{
    int size();
}

public class Tuple2<T1,T2> implements Tuple
{
    public final T1 item1;
    public final T2 item2;

    public Tuple2(
        final T1 item_1,
        final T2 item_2)
    {
        item1 = item_1;
        item2 = item_2;
    }

    @Override
    public int size()
    {
        return 2;
    }
}

public class Tuple3<T1,T2,T3> implements Tuple
{
    public final T1 item1;
    public final T2 item2;
    public final T3 item3;

    public Tuple3(
        final T1 item_1,
        final T2 item_2,
        final T3 item_3)
    {
        item1 = item_1;
        item2 = item_2;
        item3 = item_3;
    }

    @Override
    public int size()
    {
        return 3;
    }
}
4
ответ дан 28 November 2019 в 22:33
поделиться

Вы должны посмотреть на реализацию .NET в Tuple . Они безопасны во время компиляции.

3
ответ дан 28 November 2019 в 22:33
поделиться

Какова цель typeLock? Разрешить кому-то помешать построить еще какие-нибудь из этих объектов? Эта часть не имеет особого смысла.

Почему вы хотите позволить кому-либо предотвратить дальнейшую реализацию ваших объектов? Если по какой-то причине это то, что вам нужно, вместо того, чтобы «блокировать» класс и создавать исключения, просто убедитесь, что путь к коду ... не создает больше объектов этого типа.

Какова цель статического lastTuple, который устанавливается в качестве ссылки на последний экземпляр Tuple? Это плохая практика, чтобы смешивать статические ссылки, как это.

Честно говоря, код довольно запутанный, хотя необходимость в этом классе сбивает с толку. Если бы это был какой-то код, который я просматривал в рабочей среде, я бы этого не допустил.

1
ответ дан 28 November 2019 в 22:33
поделиться

видел этот код в волновом проекте

public class Tuple<A> {

  private final A[] elements;

  public static <A> Tuple<A> of(A ... elements) {
    return new Tuple<A>(elements);
  }

  public Tuple(A ... elements) {
    this.elements = elements;
  }

  public A get(int index) {
    return elements[index];
  }

  public int size() {
    return elements.length;
  }

  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }

    if (o == null || o.getClass() != this.getClass()) {
      return false;
    }

    Tuple<A> o2 = (Tuple<A>) o;
    return Arrays.equals(elements, o2.elements);
  }

  @Override
  public int hashCode() {
    return Arrays.hashCode(elements);
  }

  @Override
  public String toString() {
    return Arrays.toString(elements);
  }
}
1
ответ дан 28 November 2019 в 22:33
поделиться

Вот действительно ужасная реализация с n-кортежами, в которой используются универсальные средства для проверки типов во время компиляции. Основной метод (предоставленный для демонстрационных целей) показывает, насколько ужасным было бы это использовать:

interface ITuple { }

/**
 * Typed immutable arbitrary-length tuples implemented as a linked list.
 *
 * @param <A> Type of the first element of the tuple
 * @param <D> Type of the rest of the tuple
 */
public class Tuple<A, D extends ITuple> implements ITuple {

    /** Final element of a tuple, or the single no-element tuple. */
    public static final TupleVoid END = new TupleVoid();

    /** First element of tuple. */
    public final A car;
    /** Remainder of tuple. */
    public final D cdr;

    public Tuple(A car, D cdr) {
        this.car = car;
        this.cdr = cdr;
    }

    private static class TupleVoid implements ITuple { private TupleVoid() {} }

    // Demo time!
    public static void main(String[] args) {
        Tuple<String, Tuple<Integer, Tuple<String, TupleVoid>>> triple =
                new Tuple<String, Tuple<Integer, Tuple<String, TupleVoid>>>("one",
                        new Tuple<Integer, Tuple<String, TupleVoid>>(2,
                                new Tuple<String, TupleVoid>("three",
                                        END)));
        System.out.println(triple.car + "/" + triple.cdr.car + "/" + triple.cdr.cdr.car);
        //: one/2/three
    }
}
1
ответ дан 28 November 2019 в 22:33
поделиться

Если вы действительно заинтересованы в написании безопасных для типов контейнеров, посмотрите на дженерики:

public class Tuple<T> {
  private final T[] arr;
  public Tuple (T... contents) {
    arr = contents;  //not sure if this compiles??
  }

  // etc

  public static final void main(String[] args) {
    Tuple<String> stringTuple = new Tuple<String>("Hello", "World!");
    Tuple<Integer> intTuple = new Tuple<Integer>(2010,9,4);
  }
}
0
ответ дан 28 November 2019 в 22:33
поделиться
Другие вопросы по тегам:

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