Это сработало для меня:
ios sdk 9.3
в настройке сборки для допустимой архитектуры app.xcodeproj: armv7 armv7s Build Active architecture: No
Очистите и постройте, сработали для меня.
Программирование на интерфейсе означает соблюдение «контракта», созданного с использованием этого интерфейса. И поэтому, если ваш интерфейс IPoweredByMotor
имеет метод start()
, будущие классы, которые реализуют интерфейс, будь то MotorizedWheelChair
, Automobile
или SmoothieMaker
, при реализации методов этого интерфейса добавят гибкости вашей системе потому что один кусок кода может запустить двигатель множества различных типов вещей, потому что все, что нужно знать одному коду, - это то, что они отвечают start()
. Неважно , как они начинают, просто они должны начинать .
Существуют некоторые превосходные ответы здесь, но если Вы ищете конкретную причину, посмотрите не далее, чем Поблочное тестирование.
Полагайте, что Вы хотите протестировать метод в бизнес-логике, которая получает текущую налоговую ставку для региона, где транзакция происходит. Чтобы сделать это, класс бизнес-логики должен говорить с базой данных через Репозиторий:
interface IRepository<T> { T Get(string key); }
class TaxRateRepository : IRepository<TaxRate> {
protected internal TaxRateRepository() {}
public TaxRate Get(string key) {
// retrieve an TaxRate (obj) from database
return obj; }
}
Всюду по коду используйте тип IRepository вместо TaxRateRepository.
Репозиторий имеет непубличного конструктора, чтобы поощрить пользователей (разработчики) использовать фабрику для инстанцирования репозитория:
public static class RepositoryFactory {
public RepositoryFactory() {
TaxRateRepository = new TaxRateRepository(); }
public static IRepository TaxRateRepository { get; protected set; }
public static void SetTaxRateRepository(IRepository rep) {
TaxRateRepository = rep; }
}
Фабрика является единственным местом, где на класс TaxRateRepository ссылаются непосредственно.
Таким образом, Вам нужны некоторые классы поддержки для этого примера:
class TaxRate {
public string Region { get; protected set; }
decimal Rate { get; protected set; }
}
static class Business {
static decimal GetRate(string region) {
var taxRate = RepositoryFactory.TaxRateRepository.Get(region);
return taxRate.Rate; }
}
И существует также другая другая реализация IRepository - насмешка:
class MockTaxRateRepository : IRepository<TaxRate> {
public TaxRate ReturnValue { get; set; }
public bool GetWasCalled { get; protected set; }
public string KeyParamValue { get; protected set; }
public TaxRate Get(string key) {
GetWasCalled = true;
KeyParamValue = key;
return ReturnValue; }
}
Поскольку живой код (Бизнес-класс) использует Фабрику для получения Репозитория, в модульном тесте Вы включаете MockRepository для TaxRateRepository. После того как замена сделана, можно трудно кодировать возвращаемое значение и сделать базу данных ненужной.
class MyUnitTestFixture {
var rep = new MockTaxRateRepository();
[FixtureSetup]
void ConfigureFixture() {
RepositoryFactory.SetTaxRateRepository(rep); }
[Test]
void Test() {
var region = "NY.NY.Manhattan";
var rate = 8.5m;
rep.ReturnValue = new TaxRate { Rate = rate };
var r = Business.GetRate(region);
Assert.IsNotNull(r);
Assert.IsTrue(rep.GetWasCalled);
Assert.AreEqual(region, rep.KeyParamValue);
Assert.AreEqual(r.Rate, rate); }
}
Помните, Вы хотите протестировать метод бизнес-логики только, не репозиторий, базу данных, строку подключения, и т.д... Существуют различные тесты для каждого из тех. Путем выполнения его этот путь Вы можете абсолютно изолированный код, который Вы тестируете.
Дополнительная льгота - то, что можно также выполнить модульный тест без соединения с базой данных, которое делает его быстрее, более портативный (думайте команда мультиразработчика в удаленных местоположениях).
Другая дополнительная льгота - то, что можно использовать процесс Разработки через тестирование (TDD) для фазы реализации разработки. Я строго не использую TDD, но соединение TDD и олдскульного кодирования.
Почему простирается зло . Эта статья является прямым ответом на заданный вопрос. Я не могу представить себе почти ни одного случая, когда вам действительно понадобится абстрактный класс , и множество ситуаций, когда это плохая идея. Это не означает, что реализации, использующие абстрактные классы, являются плохими, но вам придется позаботиться о том, чтобы не сделать контракт интерфейса зависимым от артефактов какой-то конкретной реализации (пример: класс Stack в Java).
Еще одна вещь: нет необходимости или хорошей практики, чтобы везде были интерфейсы. Как правило, вы должны определить, когда вам нужен интерфейс, а когда нет. В идеальном мире второй случай должен быть реализован как финальный класс большую часть времени.
Одна из причин заключается в том, что интерфейсы обеспечивают рост и расширяемость. Скажем, например, что у вас есть метод, который принимает объект в качестве параметра,
public void drink (coffee someDrink) {
}
Теперь, допустим, вы хотите использовать точно такой же метод, но передать объект hotTea. Ну, ты не можешь. Вы просто жестко запрограммировали этот метод, чтобы использовать только кофейные объекты. Может быть, это хорошо, может быть, это плохо. Недостатком вышесказанного является то, что он строго блокирует вас одним типом объекта, когда вы хотите передать все виды связанных объектов.
Используя интерфейс, скажем, IHotDrink,
интерфейс IHotDrink {}
и переписав вышеописанный метод для использования интерфейса вместо объекта,
public void drink (IHotDrink someDrink) {
}
Теперь вы можете передавать все объекты, которые реализуют интерфейс IHotDrink. Конечно, вы можете написать точно такой же метод, который делает то же самое с другим параметром объекта, но почему? Вы вдруг поддерживаете раздутый код.
Программирование на интерфейсах дает несколько преимуществ:
Требуется для шаблонов типов GoF, таких как шаблон посетителей
Позволяет для альтернативных реализаций. Например, множественные реализации объекта доступа к данным могут существовать для одного интерфейса, который абстрагирует используемое ядро базы данных (AccountDaoMySQL и AccountDaoOracle могут оба реализовывать AccountDao)
Класс может реализовывать несколько интерфейсов. Java не позволяет множественное наследование конкретных классов.
Абстрагирует подробности реализации. Интерфейсы могут включать только общедоступные методы API, скрывая детали реализации. Преимущества включают четко документированный публичный API и хорошо документированные контракты.
В значительной степени используется современными структурами внедрения зависимостей, такими как http://www.springframework.org/ .
В Java интерфейсы могут использоваться для создания динамических прокси - http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Proxy.html . Это может быть очень эффективно использовано в таких средах, как Spring, для выполнения аспектно-ориентированного программирования. Аспекты могут добавить очень полезную функциональность в классы без непосредственного добавления кода Java в эти классы. Примеры этой функциональности включают ведение журнала, аудит, мониторинг производительности, разграничение транзакций и т. Д. http://static.springframework.org/spring/docs/2.5.x/reference/aop.html .
Макетные реализации, модульное тестирование. Когда зависимые классы являются реализациями интерфейсов, могут быть написаны фиктивные классы, которые также реализуют эти интерфейсы. Ложные классы могут быть использованы для облегчения модульного тестирования.
Вы можете увидеть это с точки зрения perl / python / ruby:
Я думаю, что рассмотрение интерфейсов Java в качестве аналогии с этим лучше всего объясняет это. Вы на самом деле не передаете тип, вы просто передаете что-то, что отвечает методу (черта, если хотите).
Программирование на интерфейсе означает соблюдение «контракта», созданного с использованием этого интерфейса.
Это единственное, что неправильно понимают в интерфейсах.
Нет никакого способа принудить любой такой контракт с интерфейсами. Интерфейсы, по определению, не могут указывать поведение вообще. Классы, где поведение происходит.
1114 Это ошибочное убеждение настолько широко распространено, что многие люди считают его общепринятым мнением. Это, однако, неправильно.
Итак, это утверждение в OP
Почти в каждой книге по Java, которую я читаю, рассказывается об использовании интерфейса как способа обмена состояниями и поведением между объектами
просто невозможно. Интерфейсы не имеют ни состояния, ни поведения. Они могут определять свойства, которые должны обеспечивать реализующие классы, но это настолько близко, насколько они могут получить. Вы не можете поделиться поведением, используя интерфейсы.
Можно предположить, что люди будут реализовывать интерфейс, обеспечивающий поведение, подразумеваемое именем его методов, но это совсем не то же самое. И это не накладывает никаких ограничений на то, когда такие методы вызываются (например, что Start должен вызываться перед Stop).
Это утверждение
Требуется для шаблонов типа GoF, таких как шаблон посетителей
, также неверно. Книга GoF использует абсолютно нулевые интерфейсы, поскольку они не были особенностью языков, используемых в то время. Ни один из шаблонов не требует интерфейсов, хотя некоторые могут их использовать. IMO, паттерн Observer - это тот, в котором интерфейсы могут играть более элегантную роль (хотя в настоящее время паттерн обычно реализуется с использованием событий). В шаблоне «Посетитель» почти всегда требуется базовый класс «Посетитель», реализующий поведение по умолчанию для каждого типа посещаемого узла, IME.
Лично я думаю, что ответ на этот вопрос имеет три аспекта:
Интерфейсы воспринимаются многими как серебряная пуля (эти люди обычно работают под неправильным пониманием «контракта», или думают эти интерфейсы магически развязывают их код)
Java-люди очень сосредоточены на использовании фреймворков, многие из которых (справедливо) требуют классов для реализации своих интерфейсов
Интерфейсы были лучшим способом сделать некоторые вещи до того, как были введены дженерики и аннотации (атрибуты в C #).
Интерфейсы - очень полезная языковая функция, но ими злоупотребляют. Симптомы включают в себя:
Интерфейс реализован только одним классом
Класс реализует несколько интерфейсов. Часто рекламируется как преимущество интерфейсов, обычно это означает, что рассматриваемый класс нарушает принцип разделения интересов.
Существует иерархия наследования интерфейсов (часто отражается иерархией классов). Это ситуация, которую вы пытаетесь избежать, используя интерфейсы в первую очередь. Слишком большое наследование - это плохо, как для классов, так и для интерфейсов.
Все эти вещи - запахи кода, ИМО.
Я принял бы (с @eed3s9n), что он должен способствовать слабой связи. Кроме того, без интерфейсов поблочное тестирование становится намного более трудным, поскольку Вы не можете копировать свои объекты.
В одном смысле я думаю, что Ваш вопрос сводится только к, "почему использование взаимодействует через интерфейс и не абстрактные классы?" Технически, можно достигнуть слабой связи и с - конкретная реализация все еще не подвергнута коду вызова, и можно использовать Шаблон "абстрактная фабрика" для возврата конкретной реализации (интерфейсная реализация по сравнению с расширением абстрактного класса) для увеличения гибкости дизайна. На самом деле Вы могли утверждать, что абстрактные классы дают Вам немного больше, так как они позволяют, Вы обоим требуете, чтобы реализации удовлетворили Ваш код ("НЕОБХОДИМО реализовать, запускаются ()"), и обеспечьте реализации по умолчанию ("У меня есть стандартная краска (), можно переопределить, если Вы хотите к") - с интерфейсами, реализации должны быть обеспечены, который со временем может приводить к хрупким проблемам наследования через интерфейсные изменения.
Существенно, тем не менее, я использую интерфейсы главным образом из-за ограничения единичного наследования Java. Если моя реализация ДОЛЖНА наследоваться абстрактному классу, который будет использоваться кодом вызова, который означает, что я теряю гибкость для наследования чему-то еще даже при том, что это может иметь больше смысла (например, для повторного использования кода или иерархии объектов).
EXEC sp_msforeachtable "PRINT 'INSERT INTO <new_db_name>.? SELECT * FROM ?;'"
и затем выполняемый вставки. Я надеюсь, что это могло помочь кому-то сэкономить некоторое время...
– Pecan
15 February 2017 в 15:36
Это - один способ продвинуть свободный связь .
Со слабой связью, изменение в одном модуле не потребует изменения в реализации другого модуля.
А хорошее использование этого понятия Шаблон "абстрактная фабрика" . В примере Википедии интерфейс GUIFactory производит интерфейс Button. Конкретной фабрикой может быть WinFactory (производящий WinButton), или OSXFactory (производящий OSXButton). Вообразите, пишете ли Вы приложение GUI, и необходимо пойти посмотреть вокруг всех экземпляров OldButton
класс и изменение их к WinButton
. Тогда в следующем году необходимо добавить OSXButton
версия.
, Каким образом?
, поскольку это - то, что говорят все книги. Как шаблоны GoF, многие люди видят его как универсально хороший и никогда не думают о том, является ли это действительно правильным дизайном.
, Как Вы знаете все отношения между объектами, которые произойдут в том интерфейсе?
Вы не делаете, и это - проблема.
, Если Вы уже знаете те отношения, тогда почему не только расширяют абстрактный класс?
Причины не расширить абстрактный класс:
, Если ни один не применяется, идите вперед и используйте абстрактный класс. Это сохранит Вас много времени.
Вопросы Вы не спросили:
, Что оборотные стороны использования являются интерфейсом?
Вы не можете изменить их. В отличие от абстрактного класса, интерфейс установлен в камне. Как только у Вас есть одно используемое, расширение его повредит код, период.
мне действительно нужно также?
Большую часть времени, нет. Думайте действительно трудно перед созданием любой иерархии объектов. Большая проблема на языках как Java состоит в том, что он делает слишком легким создать крупные иерархии сложного объекта.
Рассматривают классический пример, который LameDuck наследовал от Утки. Звучит легким, не так ли?
ну, который является, пока Вы не должны указывать, что утка была ранена и является теперь Ламе. Или укажите, что неудачник был излечен и может идти снова. Java не позволяет Вам изменять тип объектов, таким образом с помощью подтипов, чтобы указать, что хромота на самом деле не работает.
Я думаю одна из причин, от абстрактных классов в основном отказались разработчики, могло бы быть недоразумение.
, Когда Банда Четыре записала:
Программа к интерфейсу не реализация.
не было такой вещи как интерфейс C# или Java. Они говорили об объектно-ориентированном интерфейсном понятии, что каждый класс имеет. Erich Gamma упоминает его в это интервью .
я думаю после всех правил, и принципы механически без взглядов приводит к трудному, чтобы считать, переместиться, понять и поддержать кодовую базу. Помните: самая простая вещь, которая могла возможно работать.
git add
изменения этапов (то есть, это добавляет их к индексу); git commit
создает новую локальную фиксацию, содержащую все изменения в индексе, и затем очищает индекс (потому что изменения в индексе теперь фиксировались).
– Marnen Laibow-Koser
29 April 2019 в 16:02
Большой вопрос. Я отошлю Вас к Josh Bloch в Эффективном Java, который пишет (объект 16), почему предпочесть использование интерфейсов по абстрактным классам. Между прочим, если у Вас нет этой книги, я настоятельно рекомендую его! Вот сводка того, что он говорит:
Что относительно преимущества абстрактных классов, обеспечивающих базовое внедрение? Можно предоставить абстрактному скелетному классу реализации каждый интерфейс. Это комбинирует достоинства и интерфейсов и абстрактных классов. Скелетные реализации оказывают помощь реализации, не налагая серьезные ограничения, которые вызывают абстрактные классы, когда они служат определениями типа. Например, эти Платформа Наборов определяет интерфейсы использования типа и предоставляет скелетную реализацию каждому.
По-моему, Вы видите это так часто, потому что это - очень хорошая практика, которая часто применяется в неправильных ситуациях.
существует много преимуществ для интерфейсов относительно абстрактных классов:
Вы получаете большую часть преимущества от интерфейсов при контакте с модулями кода. Однако нет никакого легкого правила определить, где границы модуля должны быть. Таким образом, эту лучшую практику легко злоупотребить, особенно сначала разрабатывая некоторое программное обеспечение.
Все о разработке перед кодированием.
, Если Вы не знаете всех отношений между двумя объектами после определения интерфейса тогда Вы сделали плохое задание определения интерфейса - который относительно легко зафиксировать.
, Если Вы погрузились прямо в кодирование и поняли, половина пути через Вас пропускает что-то, что намного более трудно зафиксировать.
Я думаю, что основной причиной использования интерфейсов в Java является ограничение на единичное наследование. Во многих случаях это приводит к ненужным сложностям и дублированию кода. Взгляните на трейты в Scala: http://www.scala-lang.org/node/126 Трейты - особый вид абстрактных классов, но класс может расширять многие из них.
.