Вы ищете io::copy
:
use std::io::{self, prelude::*, SeekFrom};
pub fn assemble(mut input: I, mut output: O) -> Result<(), io::Error>
where
I: Read + Seek,
O: Write,
{
// first seek and output "hello"
input.seek(SeekFrom::Start(5))?;
io::copy(&mut input.by_ref().take(5), &mut output)?;
// then output "world"
input.seek(SeekFrom::Start(0))?;
io::copy(&mut input.take(5), &mut output)?;
Ok(())
}
Если вы посмотрите на реализацию io::copy
, вы увидите, что он похож на ваш код. Тем не менее, он заботится о том, чтобы обрабатывать больше ошибок:
write
не всегда записывает все, что вы просите! Он также использует больший размер буфера, но все еще содержит стек.
Анд, я думаю, вы приближаетесь к этому - каламбур НЕ предназначен - с ненужной степенью абстракции. Я думаю, что этот (ИМХО) ненужный уровень абстракции является тем, что вызывает здесь «проблему». Возможно, вы приближаетесь к этому с математического теоретического подхода, когда многие из нас приближаются к этому с подхода «программист, пытающийся решить проблемы». Я считаю, что это различие в подходах вызывает разногласия.
Когда программисты смотрят на практичность и как на самом деле реализуют что-то, есть несколько раз, когда вам нужен какой-то полностью произвольный объект фактический пример которого совершенно не имеет значения. Он просто не может быть нулевым. Пример, который я дал в комментарии к другому сообщению, - это реализация *Set
(*
== Hash
или Concurrent
или тип выбора), который обычно выполняется с использованием поддержки *Map
и использования Map
в качестве набора. Вы часто не можете использовать null
как значение Map
, поэтому обычно делается попытка использовать статический экземпляр Object
как значение, которое будет игнорироваться и никогда не будет использоваться. Однако необходим некоторый ненулевой заполнитель.
Еще одно распространенное использование с ключевым словом synchronized
, где требуется некоторое Object
для синхронизации, и вы хотите обеспечить что ваш синхронизированный элемент полностью закрыт, чтобы избежать тупиковой ситуации, когда разные классы непреднамеренно синхронизируются с одной и той же блокировкой. Очень распространенная идиома заключается в том, чтобы выделить private final Object
для использования в классе как блокировку. Справедливости ради следует отметить, что по сравнению с Java 5 и java.util.concurrent.locks.Lock
и связанными дополнениями эта идиома заметно менее применима.
Исторически сложилось так, что на Java было очень полезно иметь Object
. Вы могли бы сказать, что с небольшими изменениями в дизайне или с небольшими изменениями API это больше не понадобится. Вы, вероятно, правы в этом.
И да, API мог бы предоставить класс Placeholder
, который расширяет Object
без добавления чего-либо вообще, для использования в качестве заполнителя для целей, описанных выше , Но - если вы расширяете Object
, но ничего не добавляете, каково значение в классе, кроме того, что разрешить Object
быть абстрактным? Математически, теоретически, возможно, можно было бы найти значение, но прагматически, какое значение он мог бы добавить для этого?
В программировании есть моменты, когда вам нужен объект, некоторый объект , любой конкретный объект , который не является нулевым, что вы можете сравнить с помощью ==
и / или .equals()
, но вам просто не нужна какая-либо другая функция для этого объекта. Он существует только для того, чтобы служить уникальным идентификатором и в противном случае абсолютно ничего не делает. Object
удовлетворяет эту роль отлично и (IMHO) очень чисто.
Я бы предположил, что это является частью причины, по которой Object
не был объявлен абстрактным: для него это просто не полезно.
Вы никогда не знаете, когда захотите использовать простой объект в качестве заполнителя. Подумайте об этом как о нуле в числовой системе (и null для этого не работает, поскольку null представляет отсутствие данных).
Как объект более оскорбителен, чем null?
Он делает маркер хорошего места (так же как и нуль).
Кроме того, я не думаю, что это будет
Я не говорю, что нуль - лучшая вещь, так как нарезанный хлеб - я прочитал статью на днях с помощью " Изобретатель "обсуждает стоимость / ценность понятия null ... (я даже не думал, что null является изобретательным! Я думаю, кто-то может утверждать, что он изобрел нуль ..), что возможность экземпляра объекта не хуже возможность пропускать null.
Там следует быть причиной для создания абстрактного класса. Один из них - запретить клиентам создавать экземпляр класса и заставлять их использовать только подклассы (по каким-либо причинам). Другое дело, если вы хотите использовать его в качестве интерфейса, предоставляя абстрактные методы, которые должны выполняться подклассами . Вероятно, дизайнеры и Java не видели таких причин, поэтому java.lang.Object
остается конкретным.
Как всегда, Гува приходит помочь: с помощью http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html Материал здесь может использоваться для уничтожения экземпляров nulls / Object для «не нулевого заполнителя» из кода.
Здесь есть полностью разделенные вопросы:
Определяет ли объект методы, расширяющие его классы, для реализации? Нет, и поэтому он не должен быть абстрактным.
Концепция абстрактного класса имеет четко определенное значение, которое не относится к объекту.
Вы можете создать экземпляр Object
для блокировок синхронизации:
Object lock = new Object();
void someMethod() {
//safe stuff
synchronized(lock) {
//some code avoiding race condition
}
}
void someOtherMethod() {
//safe code
synchronized(lock) {
//some other stuff avoiding race condition
}
}
Я не уверен, что это причина, но она позволяет (или разрешает, поскольку теперь есть лучшие способы сделать это) для объекта, который будет использоваться как блокировка:
Object lock = new Object();
....
synchronized(lock)
{
}