F # 3.0 dodaje ostrzejsze kontrole w odniesieniu do wywołań base
i protected
członków. Mam coś podobnego do następującej klasy abstrakcyjnej w języku C#, która ma pomocnicze metody protected static
używane przez klasy pochodne.Zrozumienie zmianę chronionego użytkowania użytkownik/bazy w F # 3,0
public abstract class Processor {
public abstract void Process();
protected static void Helper(object arg) { }
}
w F #, jedna z tych metod pomocniczych jest przekazywana jako funkcja pierwszej klasy:
type DerivedProcessor() =
inherit Processor()
let init f =
f()
override x.Process() =
init Processor.Helper
kompiluje bez zarzutu w 2,0, ale 3,0 generuje błąd:
A protected member is called or 'base' is being used. This is only allowed in the direct implementation of members since they could escape their object scope.
OK, jest to dość łatwe do spełnienia, wystarczy zawinąć rozmowę w innym statycznym członku.
static member private HelperWrapper(arg) = Processor.Helper(arg)
i przekazać tę inte. Ale dlaczego?
C# nie ma problemu z tym samym wzorem.
public class HappyToCompile : Processor {
private void Init(Action<object> f) {
f(null);
}
public override void Process() {
Init(Helper);
}
}
pytania:
- Dlaczego surowsze kontrole dodana?
- (i pokrewne) Co robi straszny problem, takie trywialne adres obejście?
- Czy istnieje lepszy design, który to ma zachęcić?
Odpowiedziałeś na pierwsze pytanie, a blog Eric odpowiada drugi. Łatwo prześwitują różnice między 'Func <_>' i 'FSharpFunc <_>'. Jak można to refaktoryzować, aby wyeliminować "chronione"? – Daniel
Dlaczego jest on chroniony? Jeśli chcesz, aby był dostępny tylko dla podklas, wtedy nie ma zbyt wiele rzeczy, które możesz zrobić. Być może mógłbyś wystawić 'Helper' jako chronioną własność typu' Action
Będzie to dobry dodatek do [_Breaking Changes_] (http://msdn.microsoft.com/en-us/library/hh416791). Kolejne [ostatnie pytanie] (http://stackoverflow.com/q/11978234/162396) może być również dobrym kandydatem. – Daniel