Я предпочитаю делать это без делегатов и сегментов. Это можно сделать с помощью пользовательского init или установив дополнительные значения.
1. Custom init
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
print(success)
})
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
private let completionClosure: ((Bool) -> Void)
init(string: String, completionClosure: ((Bool) -> Void)) {
self.completionClosure = completionClosure
super.init(nibName: nil, bundle: nil)
title = string
}
func finishWork() {
completionClosure()
}
}
2. Факультативные переменные
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB()
viewController.string = "Blabla"
viewController.completionClosure = { success in
print(success)
}
navigationController?.pushViewController(animated: true)
}
}
class ViewControllerB: UIViewController {
var string: String? {
didSet {
title = string
}
}
var completionClosure: ((Bool) -> Void)?
func finishWork() {
completionClosure?()
}
}
А как насчет универсального базового класса?
public class Poo { }
public class RadioactivePoo : Poo { }
public class BaseAnimal<PooType>
where PooType : Poo, new() {
PooType Excrement {
get { return new PooType(); }
}
}
public class Dog : BaseAnimal<Poo> { }
public class Cat : BaseAnimal<RadioactivePoo> { }
РЕДАКТИРОВАТЬ : Новое решение, использующее методы расширения и интерфейс маркера ...
public class Poo { }
public class RadioactivePoo : Poo { }
// just a marker interface, to get the poo type
public interface IPooProvider<PooType> { }
// Extension method to get the correct type of excrement
public static class IPooProviderExtension {
public static PooType StronglyTypedExcrement<PooType>(
this IPooProvider<PooType> iPooProvider)
where PooType : Poo {
BaseAnimal animal = iPooProvider as BaseAnimal;
if (null == animal) {
throw new InvalidArgumentException("iPooProvider must be a BaseAnimal.");
}
return (PooType)animal.Excrement;
}
}
public class BaseAnimal {
public virtual Poo Excrement {
get { return new Poo(); }
}
}
public class Dog : BaseAnimal, IPooProvider<Poo> { }
public class Cat : BaseAnimal, IPooProvider<RadioactivePoo> {
public override Poo Excrement {
get { return new RadioactivePoo(); }
}
}
class Program {
static void Main(string[] args) {
Dog dog = new Dog();
Poo dogPoo = dog.Excrement;
Cat cat = new Cat();
RadioactivePoo catPoo = cat.StronglyTypedExcrement();
}
}
Таким образом, Dog и Cat наследуют от Животное (как отмечено в комментариях, мое первое решение не сохранило наследование).
Необходимо явно пометить классы с помощью интерфейса маркера, что болезненно, но, возможно, это может дать вам некоторые идеи ...
ВТОРОЙ РЕДАКТИРОВАНИЕ @Svish: Я изменил код, чтобы явно показать, что метод расширения является никоим образом не применяя тот факт, что iPooProvider
наследуется от BaseAnimal
. Что вы имеете в виду под «еще более строгой типизацией»?
Может помочь, если RadioactivePoo получен из poo, а затем использовать дженерики.
Поправьте меня, если я ошибаюсь, но не весь смысл поллиморфизма в возможности вернуть RadioActivePoo если он наследуется от Пу,
Существует также этот вариант (явная реализация интерфейса)
public class Cat:Animal
{
Poo Animal.Excrement { get { return Excrement; } }
public RadioactivePoo Excrement { get { return new RadioactivePoo(); } }
}
Вы теряете возможность использовать базовый класс для реализации Cat, но с другой стороны, вы сохраняете полиморфизм между Кошка и собака.
Но я сомневаюсь, что добавленная сложность того стоит.
Это называется ковариацией возвращаемого типа и не поддерживается в C # или .NET в целом, несмотря на пожелания некоторых людей.
Что я сделал бы ту же сигнатуру, но добавил бы дополнительное предложение ENSURE
к производному классу, в котором я гарантирую, что оно вернет RadioActivePoo
. Короче говоря, я бы сделал через дизайн по контракту то, что я не могу сделать с помощью синтаксиса.
Другие предпочитают подделать вместо этого. Думаю, это нормально, но я стараюсь экономить «инфраструктурные» строки кода. Если семантика кода достаточно ясна, я счастлив, и дизайн по контракту позволяет мне добиться этого, хотя это и не механизм времени компиляции.
То же самое для дженериков, которые другие ответы предлагать.
Попробуйте следующее:
namespace ClassLibrary1
{
public interface Animal
{
Poo Excrement { get; }
}
public class Poo
{
}
public class RadioactivePoo
{
}
public class AnimalBase<T>
{
public virtual T Excrement
{
get { return default(T); }
}
}
public class Dog : AnimalBase<Poo>
{
// No override, just return normal poo like normal animal
}
public class Cat : AnimalBase<RadioactivePoo>
{
public override RadioactivePoo Excrement
{
get { return new RadioactivePoo(); }
}
}
}
Почему бы не определить защищенный виртуальный метод, который создает «Excrement», и оставить общедоступное свойство, которое возвращает «Excrement», не виртуальным. Затем производные классы могут переопределить тип возвращаемого значения базового класса.
В следующем примере я делаю Excrement не виртуальным, но предоставляю свойство ExcrementImpl, чтобы позволить производным классам предоставлять правильный Poo. Затем производные типы могут переопределить тип возвращаемого значения Excrement, скрыв реализацию базового класса.
Пример:
namepace ConsoleApplication8
{
public class Poo { }
public class RadioactivePoo : Poo { }
public interface Animal
{
Poo Excrement { get; }
}
public class AnimalBase
{
public Poo Excrement { get { return ExcrementImpl; } }
protected virtual Poo ExcrementImpl
{
get { return new Poo(); }
}
}
public class Dog : AnimalBase
{
// No override, just return normal poo like normal animal
}
public class Cat : AnimalBase
{
protected override Poo ExcrementImpl
{
get { return new RadioactivePoo(); }
}
public new RadioactivePoo Excrement { get { return (RadioactivePoo)ExcrementImpl; } }
}
}
1.) Любой сценарий CGI, который может взаимодействовать с базой данных и понимать JSON, или другой формат по вашему выбору, будет выполнять работу.
Однако, если вы знакомы с Джанго, построение вашего сервера поверх Джанго было бы самым простым, в смысле того, что вы должны узнать и сколько кода приложения вы должны написать. Казалось бы, простой сценарий CGI может получиться довольно сложным, если писать его с нуля.
Я обнаружил, что django-поршневой является удобным приложением Django для быстрого написания API-сервера в стиле REST. Он поддерживает JSON, поэтому он должен легко взаимодействовать с вашей игрой JavaScript.
2.) Самый случайный взломщик пойдет на повторную атаку и ее варианты: заглянуть в источник страницы и выполнить функцию JavaScript, перехватить HTTP-запросы и повторно отправить его (должно быть легко с дополнением Firefox, как изменения данных).
Для противодействия первому можно запутать исходный код и тело HTTP;
Последнее можно предотвратить, потребовав от всех запросов на обновление включения одноразового пароля («маркер сеанса» в статье Википедии ), которая была недавно
-121--4320846-Я думаю, что нашел способ, который не зависит от дженериков или методов расширения, а скорее от скрытия метода. Он может сломать полиморфизм, однако, поэтому будьте особенно осторожны, если вы в дальнейшем наследуете от Кота.
Я надеюсь, что этот пост все еще может помочь кому-то, несмотря на опоздание на 8 месяцев.
public interface Animal
{
Poo Excrement { get; }
}
public class Poo
{
}
public class RadioActivePoo : Poo
{
}
public class AnimalBase : Animal
{
public virtual Poo Excrement { get { return new Poo(); } }
}
public class Dog : AnimalBase
{
// No override, just return normal poo like normal animal
}
public class CatBase : AnimalBase
{
public override Poo Excrement { get { return new RadioActivePoo(); } }
}
public class Cat : CatBase
{
public new RadioActivePoo Excrement { get { return (RadioActivePoo) base.Excrement; } }
}