возвратите неизвестный Универсальный Список <T>

Конечная проблема с использованием this вместо prototype заключается в том, что при переопределении метода конструктор базового класса все равно будет ссылаться на переопределенный метод. Рассмотрим это:

BaseClass = function() {
    var text = null;

    this.setText = function(value) {
        text = value + " BaseClass!";
    };

    this.getText = function() {
        return text;
    };

    this.setText("Hello"); // This always calls BaseClass.setText()
};

SubClass = function() {
    // setText is not overridden yet,
    // so the constructor calls the superclass' method
    BaseClass.call(this);

    // Keeping a reference to the superclass' method
    var super_setText = this.setText;
    // Overriding
    this.setText = function(value) {
        super_setText.call(this, "SubClass says: " + value);
    };
};
SubClass.prototype = new BaseClass();

var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!

subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

по сравнению с:

BaseClass = function() {
    this.setText("Hello"); // This calls the overridden method
};

BaseClass.prototype.setText = function(value) {
    this.text = value + " BaseClass!";
};

BaseClass.prototype.getText = function() {
    return this.text;
};

SubClass = function() {
    // setText is already overridden, so this works as expected
    BaseClass.call(this);
};
SubClass.prototype = new BaseClass();

SubClass.prototype.setText = function(value) {
    BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};

var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

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

var A = function (param1) {
    var privateVar = null; // Private variable

    // Calling this.setPrivateVar(param1) here would be an error

    this.setPrivateVar = function (value) {
        privateVar = value;
        console.log("setPrivateVar value set to: " + value);

        // param1 is still here, possible memory leak
        console.log("setPrivateVar has param1: " + param1);
    };

    // The constructor logic starts here possibly after
    // many lines of code that define methods

    this.setPrivateVar(param1); // This is valid
};

var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0

a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0

по сравнению с:

var A = function (param1) {
    this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
    this.publicVar = value; // No private variable
};

var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
18
задан recursive 26 February 2009 в 00:47
поделиться

7 ответов

Используйте IList вместо List<T>.

25
ответ дан 30 November 2019 в 05:57
поделиться

Альтернатива тому, чтобы быть ограниченным возвратом списка объектов должна была бы или гарантировать, чтобы A и B произошли из общей базы, вводят или реализуют единый интерфейс, затем возвращают список того базового типа или интерфейса. Включайте ограничение на Общий метод для того effect:-

List<ICommon> GetData<T>() where T: ICommon
{

}
13
ответ дан 30 November 2019 в 05:57
поделиться

Если нет определенная причина, что Вы не можете определить фактический тип заранее, можно просто сделать сам метод универсальным:

public void Main() {
    List<A> a = GetData<A>();
}

public List<TType> GetData<TType>() {
     List<TType> list= new List<TType>();
     ...
     return list; 
}
7
ответ дан 30 November 2019 в 05:57
поделиться

Вы не можете непосредственно возвратиться List<T> как это.

, Почему? В основном, потому что List<A> и List<B> (или List<string> по сравнению с List<int>, который является тем же самым) рассматриваются как 2 полностью отдельных несвязанных класса.
Так же, как Вы не можете возвратиться string из функции, которая, как объявляют, возвращается int, Вы не можете возвратить Список строк от функции, которая, как объявляют, возвращает список ints. <T> вот определенный отвлекающий маневр. Вы не могли записать общий метод, который возвратил обе строки и ints также...

См. здесь для большего количества информации о такой вещи.

Поэтому то, что необходимо сделать, возвратить что-то, что оба типа получают из (что они "имеют общего".)
Как [1 112] John Rasch говорит , Вы могли возвратиться IList, (отметьте НЕ дженерик, таким образом, это - просто список object с, или просто возвратите его как object. К сожалению, нет никакого способа сохранить тип списка.

9
ответ дан 30 November 2019 в 05:57
поделиться

РЕДАКТИРОВАНИЕ на ответ Orion ниже, добавленное ограничение, которое AnthonyWJones предложил

Вы, вероятно, должно иметь интерфейс/абстрактный класс, который A и B наследовали от

    public interface IMyInterface { }
    public class A : IMyInterface { }
    public class B : IMyInterface { }

    public List<IMyInterface> GetData<T>() where T : IMyInterface
    {
        List<IMyInterface> myList = new List<IMyInterface>();
        if (typeof(T) == typeof(A))
        {
            myList.Add(new A());
        }
        if (typeof(T) == typeof(B))
        {
            myList.Add(new B());
        }
        return myList;
    }
5
ответ дан 30 November 2019 в 05:57
поделиться

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

, Если Ваша функция значительно изменяет поведение (как изменяющийся тип возврата) на основе аргумента, то это должны, вероятно, быть две функции.

похоже, что эта функция не должна быть родовой, и должна на самом деле быть двумя функциями.

public void Main() {
    List<A> a = GetDataA();
}

public List<A> GetDataA() {
     List<A> a= new List<A>() 
     ...
     return a; 
}
public List<B> GetDataB() {
     List<B> b= new List<B>() 
     ...
     return b; 
}
1
ответ дан 30 November 2019 в 05:57
поделиться

Недавно мне пришлось решать похожую проблему, где ни одно из предложенных решений не было удовлетворительным; ограничение параметра типа было непрактичным. Вместо этого я позволяю потребителям метода решать, как изменять данные . Например, вы можете написать общую версию String.Split (), которая возвращает строго типизированный список, при условии, что вы укажете ему, как преобразовать подстроки в T.

Как только вы захотите переложить ответственность вверх по стеку вызовов ( и вам будет удобно передавать лямбды), вы можете обобщить этот шаблон произвольно. Например, если способ GetData () варьируется (как, по-видимому, предполагают некоторые ответы), вы также можете поднять эту функцию в область действия вызывающего.

Демо:

static void Main(string[] args)
{
    var parseMe = "Hello world!  1, 2, 3, DEADBEEF";

    // Don't need to write a fully generic Process() method just to parse strings -- you could 
    // combine the Split & Convert into one method and eliminate 2/3 of the type parameters
    List<string> sentences = parseMe.Split('!', str => str);
    List<int> numbers = sentences[1].Split(',', str => Int32.Parse(str, NumberStyles.AllowHexSpecifier | NumberStyles.AllowLeadingWhite));

    // Something a little more interesting
    var lettersPerSentence = Process(sentences,
                                     sList => from s in sList select s.ToCharArray(),
                                     chars => chars.Count(c => Char.IsLetter(c)));
}

static List<T> Split<T>(this string str, char separator, Func<string, T> Convert)
{       
    return Process(str, s => s.Split(separator), Convert).ToList();
}

static IEnumerable<TOutput> Process<TInput, TData, TOutput>(TInput input, Func<TInput, IEnumerable<TData>> GetData, Func<TData, TOutput> Convert)
{
    return from datum in GetData(input)
           select Convert(datum);
}

Гуру функционального программирования, вероятно, будут зевать на это исследование: " ты'

2
ответ дан 30 November 2019 в 05:57
поделиться
Другие вопросы по тегам:

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