Przygotowuję się do moich finałów i próbuję rozwiązać problemy z ćwiczeniami z tyłu podręcznika, kiedy natknąłem się na to pytanie:

W Javie, jeśli betonowy typ p jest foo, p.getClass () i foo.class zwrócą to samo. Wyjaśnij, dlaczego nie można zagwarantować podobnej równoważności w Ruby, Pythonie lub JavaScript.

Czy ktoś może zrzucić na to światło. Z góry dziękuję!

2
Justin Carrey 8 grudzień 2013, 13:13

3 odpowiedzi

Najlepsza odpowiedź

Ruby, Python i JavaScript są wszystkimi dynamicznie typowymi językami, ale nie jest to kwestia statycznego vs. dynamicznego pisania. Raczej uważam, że ma to zrobić z faktem, że Java's getClass() jest ostateczny (nie może zostać zastąpiony), podczas gdy inne języki nie mają takich ograniczeń:

# Ruby
class Foo
  def class­()
    retur­n Strin­g
  end
end
String.new().class() == String # => true
Foo.new().class() == Foo # => false
# Python
class Foo: pass
class Bar: pass
p = Foo()
p.__class__ == Foo # => True
p.__class__ = Bar
p.__class__ == Foo # => False
// JavaScript
function Foo() { }
function Bar() { }
var p = new Foo();
p.constructor == Foo; // => true
p.constructor = Bar;
p.constructor == Foo; // => false

Co ciekawe, w przypadku Pythona Ustawianie członka __class__ faktycznie wpływa na wyszukiwanie metody, aby można było twierdzić, że beton typ p jest teraz Bar, który nie narusza równoważności.

1
tom 8 grudzień 2013, 10:27

Odpowiedź jest silnie wpisana vs słabo wpisane języki programowania. W Javie (lub C ++, C #, VB itp.) Typ musi być wyraźnie zdefiniowany w czasie kompilacji. Powiedzmy więc, że masz zajęcia w Javie, który wygląda tak:

class Foo{
    String a;
    public void DoNothing(){}
}

W chwili, gdy trafiłeś przycisku kompilacji, twoja klasa jest ustalona; Nie możesz go zmienić w czasie wykonywania. To znaczy, powiedzmy, że masz zmienną P, która jest instancją foo, nie możesz zrobić:

p.b = 12345;

Kompiluje cię na ciebie. I wiesz na pewno, p będzie miał właściwość "A", musi być ciągiem i metodą donothing (), która zwraca żadnego typu.

Z drugiej strony JavaScript, nie ma koncepcji "klasy", ponieważ możesz dynamicznie dodawać (lub usunąć) właściwości lub pól do obiektu w czasie wykonywania. Więc możesz zrobić:

var x = {}; //declares a new object, it is empty right now
x["name"] = "Hello World!";
x.doWork = function() { ... };

Rezultatem jest, nie będziesz wiedział, czy zmienna "X" zawiera pole o nazwie "nazwa" lub funkcja zwana "Dowork" do momentu wykonania tej linii w czasie wykonywania.

Ten sam argument ma zastosowanie do Pythona i Ruby.

1
kevin 8 grudzień 2013, 09:26

Nie jesteśmy pewni, o co pyta.

Jeśli masz w Pythonie

class Foo(object):
    pass

p = Foo()

Następnie p.__class__ Wróciłby Foo jako obiekt. Nazwa klasy można wydrukować

p.__class__.__name__

Lub na klasie

Foo.__name__

Oczywiście w Pythonie możesz zrobić coś takiego

class Foo2(object):
    pass

p.__class__ = Foo2

Ale tak, to język dynamiczny.

Więc ostatnia opcja jest dość rzadka i ogólnie nie widzę różnicy.

1
twil 8 grudzień 2013, 09:46