, там C#, но на Nemerle точно также. И там только переопределение и расширение функциональности, через базовый класс не обратиться всё равно, т.е. такой метод защищает от ошибок переопределения, но не эмулирует virtual/override.
Чтобы стало понятнее почему их нет — представь следующую ситуацию: одна базовая страница и три наследника с гипотетическим "static override". Ты вызываешь BasePage.GetPageUrl, теперь компилятору нужно понять, какого именно наследника сделавшего override вызвать. Ну и как? Если же ты хочешь вызвать именно Derived1.GetPageUrl, то это уже не override, т.к. тип ты указал, а обычный static new. И если надо заиспользовать функциональность BasePage, то просто вызови из него BasePage.GetPageUrl если надо.
Обычно всю логику переходов по страницам выносят или в SiteMap (сделав свою реализацию) или в отдельный класс отвечающий за редиректы. Где и как хранить или создавать экземпляры этого класса зависит уже от того откуда ты делаешь редиректы. Если же надо не просто переходы, а что-то более сложное — то тут уже надо разбирать детально что именно. Может хватить просто по каким-то критериям определять какую именно страницу вызывать, и тогда хватает тех static что есть. А может лучше свой HTTP handler писать, и всю логику в него, в том числе и логику разных реализаций GetPageUrl.
D>1. Что лучше передавать в качестве функции в Nemerle: делегат f:Func<IDataReader, T> func или функцию f:IDataReader->T ? D>Как будет выглядеть конструкция с using (var connection = new SqlConnection(this.ConnectionString)) ?
Практически точно также:
using(def connection = SqlConnection(this.ConnectionString))
{
}
//есть версия с перехватом исключений в блоке:using(def connection = SqlConnection(this.ConnectionString))
{
}
catch
{
| e is SqlException => Console.WriteLine("Не соединились!");
}
D>2. Есть ли в Nemerle параметры по-умолчанию?
Да.
public static Test(i : int = 5) : void
D>3. Есть ли в Nemerle extension методы?
Да. Только их не обязательно выносить в статический класс, в обычных тоже можно объявлять. public static почему-то оставили, хотя имхо было бы удобнее если бы можно было иметь и локальные и экземплярные тоже
public static Ext(this s : string) : string
D>4. Есть ли в Nemerle циклы for и yield return?
for(mutable i=0; i<10; i++)
{
Console.WriteLine(i);
}
//есть возможность добавить блок "иначе" выполняющийся если тело цикла не выполнялось:for(mutable i=0; i<-10; i++)
{
Console.WriteLine(i);
} otherwise
{
Console.WriteLine("Цикл не выполнялся вовсе!");
}
Здравствуйте, Darooma, Вы писали:
D>1. Что лучше передавать в качестве функции в Nemerle: делегат f:Func<IDataReader, T> func или функцию f:IDataReader->T ?
Если не предполагается использовать функцию за пределами Немерле, то лучше IDataReader -> T. Если предполагается использовать функцию, например, из C#, то делегат, так как с функциональным объектов в шарпе будет туго.
D>Как будет выглядеть конструкция с using (var connection = new SqlConnection(this.ConnectionString)) ?
using (connection = SqlConnection(this.ConnectionString))
// или using (def connection = SqlConnection(this.ConnectionString))
D>2. Есть ли в Nemerle параметры по-умолчанию?
Да, но инициализировать можно только литералами. Синтаксис как в шарпее: x = null. При этом можно не указывать тип параметра.
D>3. Есть ли в Nemerle extension методы?
Да.
D>4. Есть ли в Nemerle циклы for и yield return?
Да. В for важно чтобы переменная была mutable. Плюс вместо for лучше применять
foreach (i in [0..x.Length])
..
или даже
foreach (elem in collection whith i)
..
последний вариант удобен если индекс и элемент нужны одновременно.
yield модно применять как внутри метода, так и внутри выражения (см. ComputationExpressions).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
D>У C# нагляднее.
Вопрос привычек. Подход C# вводит лишнюю сущность — порядок аргументов. Причём ненадёжную в двух местах сразу — во время компиляции не выполняются ни проверки на число аргументов, ни проверки на их порядок.
Но если тебе удобно — пиши в стиле C#.
Здравствуйте, Darooma, Вы писали:
D>У C# нагляднее.
Это не у C#, а в библиотеке дотнет. Можешь использовать ее. Но по факту этот подход значительно менее удобен, так как ко всему прочему еще не позволяет выводить содержимое коллекций. Почитай внимательно документацию. Там есть пример выводящий содержимое коллекции (с помощью сплайса ..$). Это очень упрощает преобразгование в текст.
Потом в VS для $-строк есть подсветка, что делает их чтение очень удобным. В прочем, для {0} подсветка тоже имеется.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Darooma, Вы писали:
D> В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ). Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику.
VD>>Вот этот string.Format("@{0}", name) я бы заменил на: $"@$name" или еще лучше на "@" + name D>Чем это лучше?
Форматирование завязанное на порядковые номера аргументов "{0} {1} {3} {2}" — ненаглядно, и легко может привести к run-time ошибкам. "@" + name — в данном случае тупой и весьма оптимальный способ.
Строка, начинающаяся со знака «$», может иметь в себе, скажем так, активные области (splices). Если внутри строки встречается одиночный символ «$», и дальше идет выражение, то его значение вычисляется и преобразуется в строку путем вызова у результирующего объекта метода ToString(). В качестве выражения может выступать идентификатор или произвольное выражение, взятое в скобки.
Вот сравни наглядность таких выражений:
C#:
throw new InvalidArgumentException(string.Format("Неверная операция {0} для объекта {1} в состоянии {2}", cmd.OperationType, obj, obj.State));
Nemerle:
throw InvalidArgumentException($"Неверная операция $(cmd.OperationType) для объекта $obj в состоянии $(obj.State)");
Ещё интересно, что $-строка — это не захардкоженная функция языка, а макрос.
Подумал что стоит добавить ещё то что в $-строках можно производить вычесления (изредка бывает удобно), и для того чтобы в такой строке вывести сам символ $ его нужно записать два раза. Пример:
1. Что лучше передавать в качестве функции в Nemerle: делегат f:Func<IDataReader, T> func или функцию f:IDataReader->T ?
Как будет выглядеть конструкция с using (var connection = new SqlConnection(this.ConnectionString)) ?
2. Есть ли в Nemerle параметры по-умолчанию?
3. Есть ли в Nemerle extension методы?
4. Есть ли в Nemerle циклы for и yield return?
Здравствуйте, Darooma, Вы писали:
D>Я не знаю как этот вариант (когда прийду домой, скажу), но вот этот вариант не работает
Оператор <- объеявлен в пространстве имен Nemerle.Extensions. Его надо открыть перед использованием макроса.
D>Что означает оператор <-?
Инициализатор. Не что вроде C#-пного инициализатора коллекций но несколько круче. Позволяет рекурсивную инициализацию и инициализацию уже созданных объектов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Darooma, Вы писали:
D>Мне нужны. Они есть? D>Если нет, то какая альтернатива?
Паттерн синглтон.
D>Почему лямбда выражение здесь на Nemerle выглядит также ( ExecuteReader(command, reader => ......) ), как в C#? У них
же синтаксис разный.
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, Darooma, Вы писали:
D>>>>Есть ли в Nemerle статические виртуальные методы?
H>Огласите задачу, которую хотите решить этим способом. "Статический" виртуальный метод можно свести к обычному.
Есть множество страниц asp.net, у каждой из которой имеется статический метод GetPageUrlWithParams(.....). Он статический потому, что он одинаков для всех объектов данного класса (страницы), а также для того, чтобы к нему можно было обратиться напрямую в вызывающем коде.
В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ). Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Darooma, Вы писали:
D>>Мне нужны. Они есть? D>>Если нет, то какая альтернатива?
VD>Паттерн синглтон.
Он не подойдет для использования в классах (MyPage1, MyPage2, MyPage3), производных от asp.net страницы (System.Web.UI.Page, если я не ошибаюсь). У этих классов может быть множество объектов. Ведь каждый раз при обращении к странице создается новый объект.
Здравствуйте, Darooma, Вы писали:
VD>>Паттерн синглтон.
D>Он не подойдет для использования в классах (MyPage1, MyPage2, MyPage3), производных от asp.net страницы (System.Web.UI.Page, если я не ошибаюсь). У этих классов может быть множество объектов. Ведь каждый раз при обращении к странице создается новый объект.
Я отвечал на вопрос "какая есть замена для виртуальных статических методов".
Синглтоном конечно нужно делать отдельный класс. И уже его использовать из своих страниц.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, Darooma, Вы писали:
D>> В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ). Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику.
H>Зачем такой метод делать статическим?
Он статический потому, что он одинаков для всех объектов данного класса (страницы), а также для того, чтобы к нему можно было обратиться напрямую в вызывающем коде.
Это:
D>>> Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику.
И это:
D>Он статический потому, что он одинаков для всех объектов данного класса (страницы), а также для того, чтобы к нему можно было обратиться напрямую в вызывающем коде.
Взаимно-противоречивые требования.
И вообще что-то ты очень сильно мудришь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, catbert, Вы писали:
C>Здравствуйте, Darooma, Вы писали:
D>>Как по-другому я не знаю. Response.Redirect("/Secure/App/MyPage.aspx") не подходит.
C>Просто снимите модификатор static и добавьте virtual. Это как раз сценарий использования для virtual, если я все понимаю правильно.
C>Диспетчеризация виртуальных вызовов проводится как раз "по классовому принципу".
Тогда его не получится вызвать, потому что у MyPage есть множество объектов.
void Foo(){
if (good)
Response.Redirect(/*????*/);
}
Здравствуйте, Darooma, Вы писали:
D>Тогда его не получится вызвать, потому что у MyPage есть множество объектов.
Единственный раз, когда мне нужны были виртуальные статические методы — это когда я хотел виртуальные операторы, потому что они бывают только static. Во всех остальных случаях, мне кажется, они бессмысленны.
Если бы вы попробовали абстрагироваться от ASP.NET и описать проблему в терминах "класс A, класс B, метод Foo" и так далее, может будет понятнее, зачем вам такая странная вещь как виртуальные статические функции.
Здравствуйте, catbert, Вы писали:
C>Здравствуйте, Darooma, Вы писали:
D>>Тогда его не получится вызвать, потому что у MyPage есть множество объектов.
C>Единственный раз, когда мне нужны были виртуальные статические методы — это когда я хотел виртуальные операторы, потому что они бывают только static. Во всех остальных случаях, мне кажется, они бессмысленны.
C>Если бы вы попробовали абстрагироваться от ASP.NET и описать проблему в терминах "класс A, класс B, метод Foo" и так далее, может будет понятнее, зачем вам такая странная вещь как виртуальные статические функции.
Здравствуйте, catbert, Вы писали:
C>Здравствуйте, Darooma, Вы писали:
D>>foo — Это метод в другом классе, не в странице-классе MyPage.
C>А каким тогда образом Foo должен знать, какой именно метод MyPage вызывать? Если есть this, то по нему можно узнать, какой именно метод вызывается.
public partial class MyPage : System.Web.UI.Page {
protected void Page_Init(object sender, EventArgs e) { }
public static string PageUrl { get{ return"/Secure/App/MyPage.aspx";} }
}
public partial class MyPage2 : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
if (good)
Response.Redirect(MyPage.GetPageUrl);
}
}
Здравствуйте, catbert, Вы писали:
C>Здравствуйте, Darooma, Вы писали:
D>>Почитайте сообщения выше.
C>Почитал. Все равно не понимаю Пойду попью кофе.
В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ). Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику.
Здравствуйте, Darooma, Вы писали:
D>В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ). Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика. Поэтому его нужно сделать виртуальным. Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new. new заставит его переписывать по-новому, то есть делать копипаст с родительского метода и дописывать свою логику. D>
Не мог бы ты привести пример, я нисколечко не понимаю, как можно использовать виртуальный статик метод. Я не понимаю, что значит "добавлена некая логика", никакое наследование не позволяет добавить логику, максимум — вызвать базовый метод. Но вызвать базовый статик метод никакой проблемы не составляет, виртуальный он или нет.
Здравствуйте, hi_octane, Вы писали:
_>Чтобы стало понятнее почему их нет — представь следующую ситуацию: одна базовая страница и три наследника с гипотетическим "static override". Ты вызываешь BasePage.GetPageUrl, теперь компилятору нужно понять, какого именно наследника сделавшего override вызвать. Ну и как? Если же ты хочешь вызвать именно Derived1.GetPageUrl, то это уже не override, т.к. тип ты указал, а обычный static new. И если надо заиспользовать функциональность BasePage, то просто вызови из него BasePage.GetPageUrl если надо.
В C++ есть виртуальные статические функции. Как же он это делает?
Я позже создам новую тему и опишу там, что нужно сделать.
Здравствуйте, Darooma, Вы писали:
D>[i]В каждой странице он реализован одинаково, а потому он находится в базовом классе для этих страниц (которая наследуется от класса Page ).
Если он реализован одинаково, то зачем его вообще было реализовывать несколько раз?
D>Он бывает так, что этот метод должен быть реализован немного по-иному, то есть в него должна быть добавлена некая логика.
Это слишком абстрактно. Давай, лучше, ты опишешь саму задачу, а не то решение которое ты для нее придумал. А потом вместе подумаем.
D>Поэтому его нужно сделать виртуальным.
С какого перепуга? Надо другое поведение, вызывай другую функцию. Виртуальным что-то делается исключительно чтобы поведение можно было изменять в подтипах (наследниках).
D>Но именно виртаульным, чтобы его можно было реализовать по-инмоу с помощью override, а не new.
У тебя первое требование уже противоречит второму. Дальше уже можно не ходить. Ты очень странно понимаешь виртуальность методов. Статические методы и виртуальные методы не совместимы иделогически.
Есть языки (например, Delphi) в которых есть нечто похожее на виртуальные статические методы, но на самом деле это ни что иное как встраивание в язык паттерна "синглтон". Там под капотом создается объект имеющий один экземпляр и уже у него заводятся виртуальные методы. Используется это в основном как фабрика классов (опять же ОО-паттерн).
Ты же хочешь чего-то странного. Твои требования просто невозможно удовлетворить одновременно (ни на одном из существующих языков).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[21]: Помогите перевести с C#
От:
Аноним
Дата:
31.05.11 16:58
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Твои требования просто невозможно удовлетворить одновременно (ни на одном из существующих языков).
Вот условный пседокод, на C#.
public class A {
public virtual static void C() { Console.WriteLine("A"); }
}
public class B : A {
public override static void C() { Console.WriteLine("B"); base(); }
}
class Program {
public static void Main(string[] arguments) {
A.C(); // Console.WriteLine("A")
B.C(); // Console.WriteLine("B"); Console.WriteLine("A");
}
}
Компилятор, то может определить, у какого класса вызывается статический метод.
Здравствуйте, Darooma, Вы писали:
D>В C++ есть виртуальные статические функции. Как же он это делает?
Это не так. Единственный язык (из известных мне) где есть подобное — это Дельфи. Но и там это всего лишь реализация паттерна "синглтон", так что он не будет вести себя так как хочешь ты.
Описанное тобой поведение вообще не возможно, на мой взгляд.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, hi_octane, Вы писали:
D>>Я совсем не понимаю ни ваших комментариев, ни вопросов. _>В .NET нету виртуальных статических методов, и соответственно их нету ни в C# ни в Nemerle.
Между утверждениями "В .NET нету виртуальных статических методов" и "их нету ни в C# ни в Nemerle" нет никакой связи. Например, в Delphi .Net они таки есть.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: Помогите перевести с C#
От:
Аноним
Дата:
31.05.11 17:44
Оценка:
Здравствуйте, Ziaw, Вы писали:
Z>Вся затея ради base()? Что мешает вместо него написать A.C()?
В этом примере — да. Вот другой пример посложнее
class A {
protected static void C1() { C2(); }
protected virtual static void C2() { Console.WriteLine("A.C2"); }
}
class B : A {
protected override static void C2() { Console.WriteLine("B.C2"); }
}
class Program {
public static void Main(string[] arguments) {
B.C1(); // B:C2
}
}
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Darooma, Вы писали:
D>>В C++ есть виртуальные статические функции. Как же он это делает? WH>В С++ их нет.
Здравствуйте, Аноним, Вы писали:
Z>>Вся затея ради base()? Что мешает вместо него написать A.C()? А>В этом примере — да. Вот другой пример посложнее.
Мысль понятна, обычно это делается через обычные функции и синглтон.
А вообще виртуальность придумана для диспетчеризации вызовов в рантайме. Со статиком все можно вычислить в компайлтайме, видимо потому никто этим паттерном не пользуется и в подавляющем большинстве языков виртуальность для статиков не реализована.
Но! Как раз потому, что компайлайма вполне достаточно — это можно решить макросом.
module A {
public C1() : void { C2(); }
protected C2() : void { Console.WriteLine("A.C2"); }
}
[OverrideStatic] // просто копирует все методыmodule B : A {
// сгенерированный макросом методpublic C1() : void { C2(); }
protected C2() : void { Console.WriteLine("B.C2"); }
}
class Program {
public static void Main(string[] arguments) {
B.C1(); // B:C2
}
}
Здравствуйте, Аноним, Вы писали:
А>Вот условный пседокод, на C#. А>
А>public class A {
А> public virtual static void C() { Console.WriteLine("A"); }
А>}
А>public class B : A {
А> public override static void C() { Console.WriteLine("B"); base(); }
А>}
А>class Program {
А> public static void Main(string[] arguments) {
А> A.C(); // Console.WriteLine("A")
А> B.C(); // Console.WriteLine("B"); Console.WriteLine("A");
А> }
А>}
А>
Это полная бессмыслица. Точно такой же код будет без override. Только замени base() на A.C(). И наследование тут не нужно.
А>Компилятор, то может определить, у какого класса вызывается статический метод.
Это и так определяется. Ты видимо не верно понимаешь виртуальность методов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: Помогите перевести с C#
От:
Аноним
Дата:
01.06.11 14:55
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Это полная бессмыслица. Точно такой же код будет без override. Только замени base() на A.C(). И наследование тут не нужно.
Видимо вы не поняли, что смысл данного псевдокода как раз в base.
VD>Это и так определяется. Ты видимо не верно понимаешь виртуальность методов.
Вы видимо не понимаете, что перед тем как отвечать, имеет смысл посмотреть не ушла ли дискуссия дальше.