Классы и подклассы - как вы их отслеживаете?

Я и мои сокурсники (1-й год CS) борются с классами и подклассами. У нас есть тест, в котором один из вопросов проверяет понимание классов, подклассов, правового и незаконного литья между ними и т.д. Вопросы, как правило, одинаковы: Вам даются 2-3 класса с именем A, B, C, некоторые из них расширяют другие, а затем разные конструкторы и 10-15 очень запутывающих строк кода, на каждом из них нам нужно сказать, приведет ли это к одному из следующий: 1. Ошибка времени выполнения. 2. Ошибка компиляции. 3. Запустится (что будет распечатано).

Тест - это только бумага. Вопрос в том, есть ли у вас метод отслеживания различных классов и переменных? есть ли сайт, который преподает эти предметы?

Это вопрос предыдущего теста: Какая из следующих строк кода вызовет ошибку компиляции, ошибку времени выполнения и то, что будет напечатано: (я добавил решение)

A a = new A(1,2); 
B b = new B(1,2,3); 
C c = new C(1,2); 
A bb = (A) b; 
A a1; 
A a2 = null; 
System.out.println("Hello world"); //"Hello World
System.out.println(Hello world); //Compilation error
System.out.println(1/0); //Runtime Error
a = b; //Will run with no errors
a.equals(a1); //compilation error
System.out.println(a.equals(a2));//will print false. 
System.out.println(b.equals(c)); //will print true.
B aa = (B) a; //runtime error.
C bbb = (C) bb; //runtime error
C ccc = (C) b; //compilation error
a.m1(); //will print m2
b.m1(); //will print 3
c.m3(); //will print 2.
a.m5(); //will print false

Класс A:

public class A { 
 private int x; 
 public int y; 
 private C c = null; 
 public A(int x,int y){ 
 this.x = x; 
 this.y = y; 
 } 
 public void m1() { m2();} 
 public void m2() { 
 System.out.println("m2"); 
 } 
 public void m3(){ m4(); } 
 public void m4() { 
 A tmp = new B(1,2,3); 
 System.out.println(tmp.y); 
 } 
 public void m5() { 
 System.out.println((new C().equals(c))); 
 } 
 public boolean equals(Object other) { 
 if(!(other instanceof A)) return false; 
 return (((A)other).x==x & 
 ((A)other).y==y); 
 } 
}

Класс B:

public class B extends A { 
 public int y; 
 public B(int x, int y1, int y2){ 
 super(x,y1); 
 this.y = y2; 
 } 
 public void m2(){ 
 m3(); 
 } 
 public void m4() { 
 B temp = new B(1,2,3); 
 System.out.println(temp.y); 
 } 
}

Класс C:

public class C extends A { 
 public int y; 
 public C(int x, int y){ 
 super(x,y); 
 this.y = y; 
 } 
 public C(){ 
 this(0,0); 
 } 
}

Я знаю, что это долго, но я хотел, чтобы вы поняли тип вопросов... Я не ищу ответов, стараюсь помочь мне понять концепции и способы продумать это. Основные проблемы, с которыми мы боремся, связаны с тем, когда вы расширяете один класс, а затем вызываете метод внутри него, который вызывает другой метод в подклассе и так далее... Отслеживание всего, что сложно. Спасибо большое, Barak

4 ответа

ошибка компиляции обычно возникает, когда ваш синтаксис неверен или вы не создали экземпляр объекта правильно.

println (Hello World) - ошибка компиляции, потому что Hello и World пытаются ссылаться на переменную Hello и World, которые не были созданы. для решения этой части, над ней вы могли бы сказать String Hello = "Hello"; Струнный мир = "Мир"; Это решило бы ошибку-экземпляр. Но это также синтаксически неверно. если функция принимает несколько параметров, они должны быть разделены запятыми. исправить эту часть, println (Hello + World). Это ставит две строки вместе, чтобы сделать один параметр "HelloWorld", который используется в функции println().

a = b нормально, потому что оба экземпляра были созданы и из-за наследования. подумайте о наследовании как о том, что "есть", поэтому, когда B расширяет A, вы можете сказать: "B - это A". используя другой пример, форму (A) и круг (B), вы можете сказать, что "круг - это форма"

a.equals(а1); является ошибкой компиляции, поскольку a1 не был создан. для создания объекта, вам нужно использовать слово "новый"

System.out.println(a.equals(а2)); false, потому что функция equals сначала проверяет, является ли a2 "равным" A. это, поэтому он проверяет, являются ли x и y одинаковыми значениями. они не с тех пор, как x и y установлены, но a2 - всего лишь нулевой объект.

System.out.println(b.equals(с)); истинно, потому что снова "c является A", поэтому он проверяет x и y из b и c. они равны 1 и 2, так что это правда.

B aa = (B) a; a был создан и синтаксически корректен, поэтому он передает компиляцию. Однако вы можете сказать, что "B - это A", но не "A - это B", как вы не можете сказать, что "Shape is a Circle", когда он пытается запустить, он замечает это и дает ошибку времени выполнения. C bbb = (C) bb; аналогично тому, как bb является объектом A.

a.m1();//будет печатать m2. Первая (и единственная) команда, которую выполняет функция m1(), - это вызов m2(). это печатает "м2". поэтому, когда вы вызываете a.m1(), это то же самое, что и вызов a.m2().

b.m1();//будет печатать 3. так как B перезаписывает функции m2() и m4(), он вызывает m1() → m2() → m3() → m4(), а m4() создает переменную и печатает ее y стоимость. конструктор для B (x, y1, y2) устанавливает x = x; y = y1; (из функции super (x, y1)), но затем перезаписывает y с y2.

c.m3();//будет печатать 2. это сбивает с толку. как последний, это вызывает m3() → m4(). поскольку C не перезаписывает ни один из них, он использует те, которые определены A. A m4() создает A из нового B (1,2,3). Значение объекта B объекта переопределяется y2 (3), но поскольку значение A является приватным, конструктор B не может коснуться значения A x и, следовательно, не может перезаписать его.

a.m5();//будет напечатать false то же самое, что и "System.out.println(a.equals(a2)); выше. Значение c равно null, а C имеет конструктор без аргументов C(), который вызывает C (0,0). null C не совпадает с объектом C, который был создан.

Я надеюсь, что это, по крайней мере, хорошее начало в том, что вы искали, и я надеюсь, что мои объяснения имеют смысл. Иногда трудно найти баланс между объяснением (слишком много слов может ввести в заблуждение) и недостаточно. Сделайте несколько комментариев, если вам нужно уточнить.

Отредактировано - я немного добавил о частной переменной x в части c.m3()


Aheinlein

System.out.println(a.equals(а2));

команда "instanceof" не позволяет "null", хотя a2 создается как A. Таким образом, "false" будет возвращаться, потому что "a2" имеет значение null, а не потому, что понимается между ним x и y.


Есть два способа, которыми вы можете научиться, и один из способов, которыми вы можете применить свое обучение. По всей вероятности, есть больше способов, чем я перечислял, однако это не вопрос о стеке, а вопрос для педагогики.

Учебный путь № 1

Создайте несколько классов без использования вырезания и вставки. Используйте разные иерархии. Используйте System.out.println, чтобы определить, какой метод вызывается. Напишите основной метод для осуществления различных сценариев. Попытайтесь угадать, что произойдет. Затем проверьте это, используя реальность. Это базовое тестовое развитие, за исключением использования в учебной среде. Хорошо работает для практических людей.

Учебный путь № 2

Прочитайте классы и наследование. Основной учебник (и очень хорошо стоит):

http://docs.oracle.com/javase/tutorial/java/concepts/inheritance.html

Вы найдете материал, написанный на этом сайте людьми, которые на самом деле писали библиотеки. После того, как вы закончите этот учебник, есть расширенные книги по наследованию, эффект доступа, абстрактный, интерфейс, окончательный в структуре класса. Ни одна книга не может объяснить каждую из этих концепций.

Применить Обучение № 1

Как только вы подошли к случайным проблемам по вашему выбору, используя методы 1 и 2, попробуйте и запишите код в предыдущих тестах и ​​угадайте результаты, прежде чем ваша программа сообщит им. Вы начнете разрабатывать методику отслеживания путей, которые, как мы надеемся, приведут вас к правильному ответу.


Сначала используйте хорошую среду IDE (Eclipse или Netbeans), затем попробуйте различные иерархии. Я предлагаю вам O'reilly Head First Java, отличную книгу для новичков. Также есть кулинарная книга для практики.

Только вы можете улучшить себя. Начните читать сейчас.

licensed under cc by-sa 3.0 with attribution.