2015-04-22 3 views
1

У меня есть фундаментальный блок, когда дело доходит до объектов: когда вы создаете «новый» объект, он заменяет предыдущий. Если это так, то где вы помещаете создание объекта, чтобы он не заменялся повторяющимся вызовом, например while или For?Общие сведения об объектных рамках объекта

Я работаю через книгу C# и пытаюсь создать адресную книгу, используя многомерный массив в качестве моей таблицы. Моя проблема возникает каждый раз, когда я создаю «новый» массив, предыдущие данные теряются ... :-(

Если я переместлю объект Addressbook в другое место, остальная часть программы не сможет найти его. .. книги по объектно-ориентированному дизайну оставить меня путать и разочарование Надеется, вы можете пролить некоторый свет на то, где я неправильно в моем мышлении Вот моя программа:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

class Addressbook 
{ 
    public string[,] fullname; 
    public int cnt; 
} 

namespace ConsoleApp 
{ 
    class MethodParams 
    { 
     public static void Main() 
     { 
      string myChoice; 

      MethodParams mp = new MethodParams(); 
      do 
      {         
       // show menu and get input from user 
       myChoice = mp.getChoice(); 

       // Make a decision based on the user's choice 
       mp.makeDecision(myChoice); 

       // Pause to allow the user to see the results 
       Console.Write("press Enter key to continue..."); 
       Console.ReadLine(); 
       Console.WriteLine(); 
      } while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit 
     } 
//******************* 
     // show menu and get user's choice 
     string getChoice() 
     { 
      string myChoice; 
      // Print A Menu 
      Console.WriteLine("My Address Book\n"); 
      Console.WriteLine("A - Add New Address"); 
      Console.WriteLine("D - Delete Address"); 
      Console.WriteLine("M - Modify Address"); 
      Console.WriteLine("V - View Addresses"); 
      Console.WriteLine("Q - Quit\n"); 
      Console.WriteLine("Choice (A,D,M,V,or Q): "); 
      // Retrieve the user's choice 
      myChoice = Console.ReadLine(); 
      return myChoice; 
     } 
//*********************** 
     // make decision 
     void makeDecision(string myChoice) 
     { 
      Addressbook addrBk = new Addressbook(); //Create Addressbook Object 
      addrBk.fullname = new string[10, 10]; 
      addrBk.fullname[0, 0] = "Tom"; 
      addrBk.fullname[0, 1] = "Nesler"; 
      addrBk.cnt = 1; 
      switch (myChoice) 
      { 
       case "A": 
       case "a": 
        Console.WriteLine("Enter First name"); 
      String FName; 
        FName = Console.ReadLine(); 
      Console.WriteLine("Enter Last name"); 
        String LName; 
        LName = Console.ReadLine(); 
        addrBk.fullname[addrBk.cnt,0] = FName; 
        addrBk.fullname[addrBk.cnt,1] = LName; 
        this.addAddress(ref addrBk);  //Input address name 
        addrBk.cnt = addrBk.cnt + 1; 
        break; 

       case "V": 
       case "v": 
        this.viewAddresses(ref addrBk); 
        break; 
       case "Q": 
       case "q": 
        Console.WriteLine("Bye."); 
        break; 
       default: 
        Console.WriteLine("{0} is not a valid choice", myChoice); 
        break; 
      } 
     } 
//***************** 
     // insert an address 
     void addAddress(ref Addressbook addrBk) //Addr Object containing name and Address 
     { 
      Console.WriteLine("Name: {0} {1} added.", addrBk.fullname[addrBk.cnt, 0], addrBk.fullname[addrBk.cnt, 1]); 
     } 
//***************** 
     // show addresses 
     void viewAddresses(ref Addressbook addrBk) 
     { 
      Console.WriteLine("count is: {0}", addrBk.cnt); 
      for (int i=0; i < addrBk.cnt; i++) 
      { 
       Console.WriteLine("counter = {0}",i); 
       Console.WriteLine("Name: {0} {1} ", addrBk.fullname[i,0], addrBk.fullname[i,1]); 
      } 
     } 
    } 

} 
+5

«Когда вы создаете« новый »объект, он заменяет предыдущий». Само по себе это не является содержательным заявлением. У вас может быть объект x = new object(); объект y = новый объект(); 'Там никакой замены не происходит. Я подозреваю, что вам нужно более четко различать ваш разум между переменными и объектами - затем отредактируйте свой вопрос, чтобы включить пример, который * только * показывает, с чем вы смущены. (Нам не нужна загрузка кода адресной книги ... просто простейший код, который вы можете представить, чтобы продемонстрировать проблему.) –

+0

Найти = Список <- В коллекции в вашей книге. Поскольку вы следуете за книгой C#, это лучшее, что я могу сказать, чтобы вы могли понять, что вы делаете по своей собственной фазе. На самом деле, просто продолжайте читать книгу, и я бы поспорил, что в конце она расширит ваши знания. Добро пожаловать в StockOverflow. – Aizen

+0

Спасибо Aizen! Я согласен с тем, что мне нужно продолжать читать, но на данный момент мне не хватает того, как объекты создаются в одной части моей программы и используются в другой без перезаписи. Jon: Я понимаю, что X и Y являются двумя различными экземплярами одного и того же объекта и занимают два разных пространства памяти. Но что, если каждый раз, когда я запускаю метод, я создаю X снова и снова? Я думаю, что каждый раз, когда я перезаписываю предыдущий набор значений, загружаемых в объект. Это правда? –

ответ

0

Одна из вещей, с которой вы можете столкнуться, связана с переменными-членами. Одна из основных идей заключается в том, что объект инкапсулирует данные, которые он использует вместе с методами. Это означает, что эти данные доступны всем методам в объекте и не должны предоставляться в качестве аргументов метода. Эти данные хранятся в переменных-членах.

AddressBook Берем пример, вы можете видеть, что он имеет только элементы данных (fullname и cnt), но не методы. Тем не менее, ваша программа выполняет несколько операций в адресной книге, например addAddress, чтобы добавить к ней адрес и viewAddresses, чтобы показать все адреса в адресной книге на консоли.

Что типично для класса, так это то, что оно содержит как данные, так и методы. Так что в вашем случае (просто переместить некоторые из существующего кода вокруг, и применения некоторых идиоматических C# tweeks именования):

public class Addressbook 
{ 
    private string[,] _fullname; 
    private int _cnt; 

    public Addressbook() 
    { 
     // Questions: 
     // Are 10 fields really needed for firstName and lastName? 
     // What if a user adds more than 10 names. 
     _fullname = new string[10, 10]; 
    } 

    public void AddAddress(string firstName, string lastName) 
    { 
     _fullname[_cnt,0] = firstName; 
     _fullname[_cnt,1] = lastName; 
     Console.WriteLine("Name: {0} {1} added.", _fullname[_cnt, 0], _fullname[_cnt, 1]); 
     _cnt = _cnt + 1; 
    } 

    public void ViewAddresses() 
    { 
     Console.WriteLine("count is: {0}", _cnt); 
     for (int i=0; i < _cnt; i++) 
     { 
      Console.WriteLine("counter = {0}",i); 
      Console.WriteLine("Name: {0} {1} ", _fullname[i,0], _fullname[i,1]); 
     } 
    } 
} 

AddressBook класс теперь может делать все возможное, а теперь MethodParams можете использовать его, не зная, точно какAddressBook делает свою вещь. Просто нужно знать , что можно сделать.

Теперь, если мы изменим class MethodParams немного, так что мы можем дать ему адресную книгу, чтобы работать, все становится намного проще:

class MethodParams 
{ 
    private AddressBook _addressBook; 

    public MethodParams(AddressBook addressBook) 
    { 
     _addressBook = addressBook; // this is the address book we will work with 
    } 

    public static void Main() 
    { 
     string myChoice; 
     AddressBook theAddressBook = new AddressBook(); 

     MethodParams mp = new MethodParams(theAddressBook); 
     do 
     {      
      // ... this can all stay the same.   
     } while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit 

     // When we get here, theAddressBook still contains everything. 
     // We could save it to a file. 
    } 

    // ... see remarks for changes below. 
} 

Теперь в вашем методе makeDecision вы можете сделать следующее, чтобы добавить адрес:

_addressBook.AddAddress(FName, LName); 

И для просмотра всех адресов.

_addressBook.ViewAddresses(); 

Надеюсь, это поможет прояснить некоторые моменты. Вот некоторые ответы на свои вопросы в комментариях:

Эта линия public class Addressbook начинается определение класса, который является типом, так же, как string типа.

Эта линия private AddressBook _addressBook; объявляет приватную переменную член имени _addressBook, что относится к типу AddressBook и принадлежит к классу MethodParams.

В этой строке AddressBook theAddressBook = new AddressBook(); мы создаем новый экземпляр объекта типа AddressBook, который присваивается локальной переменной с именем theAddressBook.

В этой строке MethodParams mp = new MethodParams(theAddressBook); мы создаем новый объект экземпляр типа MethodParams и инициализировать его через конструктора метода public MethodParams(AddressBook addressBook), передавая ему ссылку на экземпляр объекта с именем theAddressBook как аргумент метода для параметра метода с именем addressBook.

В этой строке _addressBook = addressBook значение поставляется в addressBook конструктору (который является ссылкой на объект экземпляра theAddressBook, который мы создали ранее в этом коде), присваивается приватной переменной-члена с именем _addressBook. Теперь, когда какой-либо из методов в MethodParams использует _addressBook, т.е.например, _addressBook.AddAddress(FName, LName) они работают с экземпляром объекта theAddressBook, который мы создали.

+0

. Ваше решение имеет смысл. Я знаком с этим подходом. У меня есть путаница. 1. Чувствительность к регистру - в верхней части вашего кода вы вызываете объект: «public class Addressbook» , но всякий раз, когда вы используете этот объект, вы вызываете его «private AddressBook _addressBook;» –

+0

Какие еще вещи сбивают с толку? Вы пытались изменить свое решение в том направлении, о котором я говорил? Если да, то какие вещи вы все еще находите сложными или запутанными? – Alex

+0

Ваше решение имеет смысл. Я знаком с этим подходом. У меня есть путаница. 1. Чувствительность к регистру - в верхней части вашего кода вы вызываете объект: «public class Addressbook» , но всякий раз, когда вы используете этот объект, вы вызываете его «private AddressBook _addressBook;» Является ли это преднамеренной или опечаткой? 2. В заголовке MethodParams вы создаете приватную переменную, называемую «addressBook _addressBook»; , а затем публичный раздел MethodParams (AddressBook addressBook). Для чего нужен этот раздел? Спасибо! –

0
string a; // this is a declaration - the variable `a` is null/nothing until 
      // you assign it a value 

a = new String("Hello world"); // the variable `a` now references a String 
           // Object that contains the string "Hello world" 

a = new String("Good-bye World"); // the variable `a` now references a String 
            // Object that contains the string "Good-bye World" 

Это пример того, как вы можете потерять объект. В «старые времена» это было названо утечкой памяти. В сегодняшнем мире управляемого кода l ost объект подхватывается «сбор мусора»

Когда вы создаете экземпляр и объекты, обычно вы передаете его в какую-нибудь коллекцию подобных объектов для последующей ссылки. Возможно, это список (адрес) или словарь (строки, адреса). это то, где объект «живет», пока сама коллекция не выходит за рамки.

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

0

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

public static void Main() 
{ 
///... 
    Addressbook addrBk = new Addressbook(); 
    addrBk.fullname = new string[10, 10]; 
    addrBk.fullname[0, 0] = "Tom"; 
    addrBk.fullname[0, 1] = "Nesler"; 
    addrBk.cnt = 1; 

    do 
    { 
     // rest of code 
     mp.makeDecision(addrBk, myChoice); 
     // rest of code 
    } //while ... 
} 
    void makeDecision(Addressbook addrBk, string myChoice) 
    { 
     switch (myChoice) 
     //rest of code... 
    } 

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

+0

Я думал, что это исправит. Однако, когда я переместил его в указанное вами место, я получил 12 ошибок. Объект AddrBk не отображается методу makeDecision. Как создать статический объект для этого объекта? –

+0

AddrBk будет виден, если вы передадите его методу, но сначала вам нужно обновить метод для принятия addrBk – maque

0

Похоже, вы создаете новый объект Addressbook каждый раз, когда вызывается функция makeDecision(). Кроме того, единственной ссылкой, которую вы храните в объект Addressbook, является локальная переменная внутри этой функции (addrBk). Таким образом, когда функция makeDecision завершается, ваш код больше не сможет найти адресную книгу.

Что касается решения этой конкретной части кода ... существует несколько решений. Самое быстрое решение (но не обязательно чистое в целом) - это взять первые 5 строк вашей функции makeDecision() и поместить их в начало функции Main(). Затем просто передайте переменную addrBk в функцию makeDecision() в качестве параметра каждый раз, когда вы его вызываете.

Смежные вопросы