2011-12-31 11 views
5

Jest to w zasadzie to, co chcę zrobić:Jak zdefiniować wirtualnego gettera i setera abstrakcyjnego dla nieruchomości?

public abstract class Uniform<T> 
{ 
    public readonly int Location; 
    private T _variable; 

    public virtual T Variable 
    { 
     get { return _variable; } 
    } 
} 

public class UniformMatrix4 : Uniform<Matrix4> 
{ 
    public override Matrix4 Variable 
    { 
     set 
     { 
      _variable = value; 
      GL.UniformMatrix4(Location, false, ref _variable); 
     } 
    } 
} 

getter dla Variable będą takie same we wszystkich klasach pochodnych, ale rozgrywający musi być inna.

W rzeczywistości ... Wolałbym nie mieć klas pochodnych w ogóle (to tylko jedno wywołanie funkcji, które będzie się różnić dla każdego typu), ale nie mogę myśleć o tym, jak to zrobić.


Edit: Jeśli nie było jasne, na czym polega problem mam jest, ja otrzymuję błąd składni:

'UniformMatrix4.Variable.set': cannot override because 'Uniform.Variable' does not have an overridable set accessor

I nie jestem pewien, jak stworzyć "nadpisywalny zestaw akcesoriów" ... virtual i abstract nie wydają się być dozwolone na setter.

+1

Odnośnie twojej edycji: dlatego podałem odpowiedź, którą podałem. Już wcześniej zastanawiałem się nad tym problemem. –

Odpowiedz

8

Nie można tego zrobić w języku C#, ale jako obejście można to zrobić. Wymagałoby to wywołania funkcji ustawiającej abstrakcje, która mogłaby zostać zmieniona przez klasy pochodne, pozostawiając normę nienaruszoną. Czy to działa?

public abstract class Uniform<T> 
{ 
    public readonly int Location; 
    protected T _variable; 

    public T Variable 
    { 
     get { return _variable; } 
     set { SetVariable(value); } 
    } 

    protected abstract void SetVariable(T value); 
} 

public class UniformMatrix4 : Uniform<Matrix4> 
{ 
    public override void SetVariable(Matrix4x4 value) 
    { 
     _variable = value; 
     GL.UniformMatrix4(Location, false, ref _variable); 
    } 
} 
+0

Tak, to by działało. Kosztem dodatkowego wirtualnego wywołania funkcji. –

+0

Ciekawe rozwiązanie! A to zmusiłoby klasy pochodne do zaimplementowania setera. Nie tak czysty, ale bezpieczniejszy. Lubię to! – mpen

+0

Jeśli to robisz, 'Variable' nie musi być już wirtualny. – Gabe

2

Nie można tego zrobić w języku C#. Musisz dodać program ustawiający do klasy bazowej i sprawić, aby rzucił wyjątek "Nieprawidłowe operacje".

+0

Myślę, że 'NotImplementedException' ma więcej sensu, ale wygląda na to, że działa teraz: D – mpen

+0

Właściwie możesz mieć rację co do wyjątku; na przykład klasa ReadOnlyCollection rzuca, jeśli spróbujesz ją zmodyfikować. –

6

Trzeba będzie to zrobić:

public abstract class Uniform<T> 
{ 
    public readonly int Location; 

    public virtual T Variable 
    { 
     get; set; 
    } 
} 

public class UniformMatrix4 : Uniform<Matrix4> 
{ 
    public override Matrix4 Variable 
    { 
     get 
     { 
      return base.Variable; 
     } 
     set 
     { 
      base.Variable = value; 
      GL.UniformMatrix4(Location, false, ref value); 
     } 
    } 
} 

Jak rozumiem, zachowanie zostanie oczekiwany.

Mam nadzieję, że to pomaga.

+1

'_variable' powinno być' wartością' po usunięciu mojego elementu pomocniczego, ale wystarczająco blisko! Nie sądziłem, że mógłbym to zrobić bez niego. – mpen

+0

Naprawiłem to. Dzięki! – ivowiblo

Powiązane problemy