Большинство ответов здесь, кажется, упускают из виду весь смысл. Полиморфизм можно использовать не только между экземплярами, но и между типами. Это часто необходимо, когда мы используем дженерики.
Предположим, у нас есть параметр типа в универсальном методе, и нам нужно сделать с ним некоторую операцию. Мы не хотим мгновенно, потому что мы не знаем конструкторов.
Например:
Repository GetRepository<T>()
{
//need to call T.IsQueryable, but can't!!!
//need to call T.RowCount
//need to call T.DoSomeStaticMath(int param)
}
...
var r = GetRepository<Customer>()
К сожалению, я могу придумать только «некрасивые» альтернативы:
Использовать отражение [1118 Уродлив и бьет идею интерфейсов и полиморфизма.
Создать полностью отдельный фабричный класс
Это может значительно увеличить сложность кода. Например, если мы пытаемся смоделировать доменные объекты, каждому объекту потребуется другой класс репозитория.
Создавать и вызывать нужный интерфейсный метод
Это может быть сложно реализовать, даже если мы контролируем источник для классов, используемых в качестве общих параметров. Причина в том, что, например, нам может потребоваться, чтобы экземпляры были только в хорошо известном состоянии «подключен к БД».
Пример:
public class Customer
{
//create new customer
public Customer(Transaction t) { ... }
//open existing customer
public Customer(Transaction t, int id) { ... }
void SomeOtherMethod()
{
//do work...
}
}
Чтобы использовать момент для решения проблемы статического интерфейса, нам нужно сделать следующее:
public class Customer: IDoSomeStaticMath
{
//create new customer
public Customer(Transaction t) { ... }
//open existing customer
public Customer(Transaction t, int id) { ... }
//dummy instance
public Customer() { IsDummy = true; }
int DoSomeStaticMath(int a) { }
void SomeOtherMethod()
{
if(!IsDummy)
{
//do work...
}
}
}
Это, очевидно, некрасиво, а также излишне усложняет код для всех других методов. Очевидно, что это тоже не элегантное решение!
Если в вашем примере вы хотите атомарно обновить значение в единственном документе (строка в реляционной терминологии), вы можете сделать это в CouchDB. Вы получите ошибку конфликта при попытке зафиксировать изменение, если другой конкурирующий клиент обновил тот же документ после того, как вы его прочитали. Затем вам нужно будет прочитать новое значение, обновить и повторить фиксацию. Существует неопределенное (возможно, бесконечное, если существует лот разногласий) количество раз, которое вам, возможно, придется повторить этот процесс, но вы гарантированно получите документ в базе данных с атомарно обновляемым балансом, если ваш фиксация завершается успешно.
Если вам нужно обновить два баланса (то есть перевод с одного аккаунта на другой), тогда вам нужно использовать отдельный документ транзакции (фактически другую таблицу, где строки являются транзакциями), в котором хранится сумма и два счета (входящий и исходящий). Кстати, это обычная бухгалтерская практика. Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.
Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов. Поскольку CouchDB вычисляет представления только по мере необходимости, на самом деле все еще очень эффективно вычислять текущую сумму в учетной записи на основе транзакций, которые перечисляют эту учетную запись. В CouchDB вы должны использовать функцию карты, которая выдавала номер учетной записи в качестве ключа и сумму транзакции (положительная для входящей, отрицательная для исходящей). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов. отрицательный для исходящих). Ваша функция уменьшения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов. отрицательный для исходящих). Ваша функция сокращения просто суммирует значения для каждого ключа, выдавая тот же ключ и общую сумму. Затем вы можете использовать представление с group = True для получения балансов по счетам, привязанных к номерам счетов.