2011-09-25 16 views
7
import std.stdio; 

class IntegerContainer 
{ 
    public int Integer = 1; 
} 

void DoubleInteger(IntegerContainer Container) 
{ 
    Container.Integer *= 2; 
} 

void main() 
{ 
    IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one. 
    DoubleInteger(Container); // Internal integer changes to two inside the function. 
    writefln(Container.Integer); // Prints "2." 
} 

W D wartość referencyjna względem wartości jest cechą typu, a nie parametru funkcji. Pochodzę z C++, to jest dla mnie naprawdę złe.Jak przekazać obiekt według wartości?

Wygląda na to, że istnieje słowo kluczowe ref wymuszające przekazywanie referencji dla funkcji akceptujących s. struct. Czy istnieje odpowiednik dla przekazania wartości class es?

Na przykład, powiedzmy, że chcę utworzyć funkcję funkcji, która zwraca posortowaną kopię niestandardowej klasy kontenera. W języku C++ jest to tak proste jak używanie Foo Sorted(Foo Object), w przeciwieństwie do Foo Sort(Foo& Object). Nie widzę możliwości zrobienia tego w D bez ręcznego kopiowania obiektu.

+1

nawet z obiektami zajęć, nadal jest wartością dodatkową, ponieważ jest to odniesienie, które przechodzisz, o wartości – newacct

+3

@newacct Myślę, że każdy wie, co rozumie się przez "przekazywanie wartości". – Maxpm

Odpowiedz

11

Klasy są typami odniesienia według projektu. Nie powinny być przekazywane według wartości. Dokładnie tak samo jest z Javą i C#. Jednak w przeciwieństwie do Javy i C#, D ma również w pełni zdefiniowane przez użytkownika typy wartości, ponieważ ma strukturę (C# ma również strukturę, ale są one o wiele bardziej ograniczone). Fakt, że C++ łączy oba, powoduje problemy, takie jak: object slicing.

Teraz, oczywiście, tam razy, gdy chcesz skopiować typ odniesienia. Rozwiązaniem tego problemu jest cloning. Dajesz klasie funkcję clone, która zwraca kopię obiektu, do którego jest wywoływana. W ten sposób możesz go skopiować, gdy zajdzie taka potrzeba, a zostanie on skopiowany tylko wtedy, gdy będzie potrzebny. Java i C# mają standardową funkcję clone, którą większość typów implementuje, ale z jakiegokolwiek powodu D nie. Nie jestem pewien dlaczego. Ale nadal łatwo jest zadeklarować taką funkcję dla własnych typów. Po prostu nie będzie to na Object, co pozwoliłoby na użycie go na praktycznie dowolnym obiekcie klasy bez dbania o to, jaki był rzeczywisty typ w Javie i C#. Zawsze możesz utworzyć konstruktor kopii, jeśli wolisz, ale jest mniej elastyczny, ponieważ musisz znać typ kopiowanego obiektu, podczas gdy z clone, może to być dowolny typ pochodzący z typu, który zwraca clone (co być Object w przypadku Javy i C#, ale będzie to, co zdecydujesz w D, ponieważ funkcja jest niestandardowa).

+1

IIRC kilka rzeczy w D (tablice) ma właściwość 'dup'. – BCS

+0

Tak, ale zajęcia zazwyczaj nie realizują takiej funkcji. Może się jednak zdarzyć, że stanie się typowa implementacja funkcji o nazwie 'dup' zamiast' clone' (nie ma jeszcze wielu klas w standardowej bibliotece, więc nie sądzę, że konkretna funkcja klonowania była w wszystkie standardowe jeszcze). Bez względu na to, jest to ta sama koncepcja w obu kierunkach. –

+0

Ah. tak. Powinienem być bardziej zrozumiały: ponieważ inne rzeczy używają 'dup' może być dobrym pomysłem, aby nie wywoływać funkcji' clone'. Zachowanie tego samego imienia może sprawić, że kod szablonu będzie czystszy. – BCS

4

Tak, po prostu użyj struct zamiast klasy.

Ale jeśli chcesz skopiować obiekt , musisz samodzielnie zaimplementować klonowanie. Zwróć uwagę, że projektanci D nie wymyślili tego; jest dokładnie taki sam w C# i całkiem podobny w Javie. Celem jest zapobieganie nadmiernemu kopiowaniu obiektów, co jest postrzegane jako wada C++ (ponieważ jest bardzo ukryte w kodzie).

+0

Zobacz edytuj. [15char] – Maxpm

+1

@Maxpm: Zobacz pierwsze zdanie drugiego akapitu. – Mehrdad

3

Nawet w C++ to:

Foo Sorted(Foo Object) 

nie jest przydatna. Co się stanie, jeśli obiekt jest już posortowany i nie trzeba tworzyć kopii?

W języku D musisz podać clone() takich zajęć dla swojej klasy i zadzwonić w razie potrzeby.

W przeciwnym razie używaj struktur jak wspomniany Mehrdad.

Edycja: Nie jest jasne, co dokładnie powinno robić "kopiowanie obiektu". Jeśli ma w sobie tablicę obiektów, sklonuje tę tablicę? A co z zawartymi w nim odwołaniami do obiektów? W rzeczywistości dobrze, że monsieur Walter Bright, autor D, domyślnie nie zapewniał kopiowania instancji klasy.

Powiązane problemy