Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Механизм перегрузки методов "полиморфизм" 
:(
    Опции темы
initmax
Дата 5.10.2009, 11:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 24.7.2009

Репутация: нет
Всего: нет



Пытаюсь разобраться в какой полследовательности происходит перегрузка методов.

То c чем удалось разобраться:
Перегрузка методов поддерживает полиморфизм,
 поскольку это один из способов реализации в Java концепции
 "один интерфейс, несколько методов". Для пояснения приведем
 следующие рассуждения. В тех языках, которые не поддерживают
 перегрузку методов, каждому методу должно быть присвоено уникальное имя.


1) При вызове метода компилятор проверяет объявленный тип объекта и имя метода  
например вызов x.f(args) неявный параметр х объявлен как экземпляр класса С.
Но может существовать несколько методов с именем f, поэтому компилятор нумерует все методы с общедоступным именем f в подклассе и суперклассе.

2) Вторым шагом происходит определение типов параметров указанных при вызове метода
например
f(String);
f(int);
f(char);
...
данный процесс называется разрешением перегрузки


теперь тестим


Код

import java.util.*;
import java.io.*;
import java.lang.*;


class count{

    private int odd_num=0;
    private int buff=0;

    private int countWord=0;
    private int Latin=0;


    public int test_method(int a) { return a+100; }
    public double test_method(double a) { return -100; }
    public float test_method(float a) { return -100; }
   

    public int xcount(int arr[]){

        for(int i=0; i<arr.length; i++)
        {
            if(arr[i]%2 != 0){ this.buff++; }
            if(arr[i]%2 == 0){ this.buff=0; }
            if(odd_num < buff ) { odd_num = buff; }
        }

           return odd_num;
    }


    public int xcount(char arr[]){

        for(int j=1; j<arr.length; j++)
        {

            if (java.util.regex.Pattern.matches("[^a-zA-Z ]", String.valueOf(arr[j])))
            {
            //    System.out.print(arr[j]);
                this.Latin=1;
            }

            if(arr[j] == ' ' && arr[j-1] != ' ')
            {
                if(this.Latin == 0) { this.countWord++; }
                else this.Latin=0;
            }

        }

        return this.countWord;
    }


}

  /**
 * * @author Max ITS 05v-1
 */
public class Main {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

       int count_word=0;
       int count_num=0;

       int arr_num[] = {1,2,3,3,3,3,4,5,8,7,7,7,7,7,2};
       char arr_sym[] = {' ',' ','h','e','l','l','o',' ','I','S','A',' ',' ',' ','w','o','w',' ','Q','S','6',' ',' ',' '};



       count Obj = new count();
       count_num = Obj.xcount(arr_num);
       count_word = Obj.xcount(arr_sym);

       System.out.println("Count word latin letter ="+count_word);
       System.out.println("Count odd number in row ="+count_num);

       byte a = 10;
       short a1 = 10;
       char a2 = '2';
       

       System.out.println("test call byte == "+Obj.test_method(a));
       System.out.println("test call short == "+Obj.test_method(a1));
       System.out.println("test call char == "+Obj.test_method(a2));

    }

}



как видно из кода одноимённые методы имеют разные типы но отличные от byte, short , char
public int test_method(int a) { return a+100; }
public double test_method(double a) { return -100; }
public float test_method(float a) { return -100; }

а при их вызове передаётся именно byte, short , char.
но вызывается каждый раз метод int.
Интуитивно чую что есть некое дерево типов, в котором int имеет повышенный приоритет
1) как работает этот механизм
2) как это называется, посоветуйет линк


З.Ы.
Есть метод который принимает вот такую строку, необходимо посчитать количество слов которые содержат только латинские буквы нижнего/верхнего регистров
char arr_sym[] = {' ',' ','h','e','l','l','o',' ','I','S','A',' ',' ',' ','w','o','w',' ','Q','S','6',' ',' ',' '};

вот решение

 
Код

 public int xcount(char arr[]){

        for(int j=1; j<arr.length; j++)
        {

            if (java.util.regex.Pattern.matches("[^a-zA-Z ]", String.valueOf(arr[j])))
            {
            //    System.out.print(arr[j]);
                this.Latin=1;
            }

            if(arr[j] == ' ' && arr[j-1] != ' ')
            {
                if(this.Latin == 0) { this.countWord++; }
                else this.Latin=0;
            }

        }

        return this.countWord;
    }


Можно ли более оптимально решить задачу?
Спасибо за внимание.


   


PM MAIL   Вверх
mbasil
Дата 5.10.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 2
Всего: 13



Не путайте (1) перегрузку методов и  (2) полиморфизм (переопределение)

Для полиморфизма необходимо, чтобы сигнатура метода в родительском классе и классе потомке была ОДИНАКОВА (с некоторыми исключениями). Для проверки правильности одинаковой сигнатуры компилятором мы используем аннотацию @Override.

Для перегрузки методов НЕОБХОДИМО наличие  разных типов параметров или разное их количество. То есть при одинаковом названии это разные методы.


PM MAIL   Вверх
ivanovpv
Дата 5.10.2009, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Варвар
**


Профиль
Группа: Участник
Сообщений: 639
Регистрация: 26.1.2005
Где: Москва

Репутация: 4
Всего: 28



Цитата(initmax @  5.10.2009,  11:45 Найти цитируемый пост)
public int test_method(int a) { return a+100; }
public double test_method(double a) { return -100; }
public float test_method(float a) { return -100; }

а при их вызове передаётся именно byte, short , char.
но вызывается каждый раз метод int.
Интуитивно чую что есть некое дерево типов, в котором int имеет повышенный приоритет
1) как работает этот механизм
2) как это называется, посоветуйет линк

 
Дело не в том, что int имеет некий повышенный приоритет, а в том, как вы вызываете test_method(). Скорее всего вызываете как
Код

System.out.println("test_method="+test_method(100));

Ну и получаете по умолчанию константу 100 с типом int. Соответственно и связывание происходит с методом test_method(int a);


--------------------
Aut viam inveniam aut faciam
PM MAIL Skype   Вверх
initmax
Дата 5.10.2009, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 24.7.2009

Репутация: нет
Всего: нет



Что означает "сигнатур"? в классе родителе и классе потомке должны быть одинаковы методы, только в этом случае будет организовано понятие полиморфизма ?
PM MAIL   Вверх
aleksandy
Дата 5.10.2009, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 260
Регистрация: 17.12.2006

Репутация: 4
Всего: 5



да
PM   Вверх
mbasil
Дата 5.10.2009, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 2
Всего: 13



Для работы полиморфизма "подписи" методов должны быть одинаковы, то есть одинаковы должны быть не только названия методов, но также количество параметров и их типы. Полиморфизм работает только в рамках наследования - "родитель-потомок". 
Перегрузка работает и в одном классе, и выполняется  при разных параметрах.
Это разные механизмы.

ЗАМЕЧАНИЕ: В полиморфных методах, в их "подписях",  могут несколько отличаться только модификатор доступа и выбрасываемые исключения.

Это сообщение отредактировал(а) mbasil - 5.10.2009, 19:25
PM MAIL   Вверх
initmax
Дата 6.10.2009, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 24.7.2009

Репутация: нет
Всего: нет



Другими словами...?:

При наличии множества объектов обладающих общим предком и имеющим одинаковые по типу, наименованию и параметрам методы но разнящихся по реализации данных методов, используется полиформизм "многоформие".В java используется так называемое позднее связываение которое позволяет произвести вызов тела метода того или иного объекта в момент выполнения программы "на лету", получая информацию из спец. фрагментов кода об адресах методов в объектах. В С++ например для осущетсления познего связывания методы должны быть объявлены как virtual. Иначе С++ осуществляет так называемое раньее связывание, которое выполняется в момент компиляции программного кода. Генерируется компилятором вызов функции с данным именем, а линкер намертво привязывает этот вызов к абсолютному адресу кода, который предполагается к выполнению. 
Пример полиморфизма организовал на следующей задачке.

Есть некоторое множество рыбаков, каждый из которых обладает идентичными методами, но отличается внутреней реализацией данных методов. Все умеют ловить рыбу, но количество улова у каждого класса рыбака различны, т.е. реализация методов различна.



Код


import java.util.*;
import java.io.*;
import java.lang.*;

/**
 *
 * @author initmax
 */

abstract class Fisher
{
   private String Name=null;
   private String FisherClass=null;
   protected double Catch=0;
   


   public Fisher(String Name, String FisherClass) {
           this.Name = Name;
           this.FisherClass = FisherClass;
   }

   abstract public double Catch_Luck();


   public double genLuck(){    
       return (double)(1 * Math.random());  //генерируем случайное число
   }


   public String get_Name() {
       return this.Name;
   }

   public String get_FisherClass() {
       return this.FisherClass;
   }

}

//-------------------
class Amateur extends Fisher
{
     private static double MaxCatch=20;

     public Amateur(String Name)
     {
       super(Name,"Любитель"); //вызов конструктора суппер класса
     }

     public double Catch_Luck(){ //переопределение абстрактного метода
         super.Catch = (this.MaxCatch * super.genLuck());
         return super.Catch;
     }
}

//-------------------
class Profi extends Fisher
{
     private static double MaxCatch=50;

     public Profi (String Name)
     {
       super(Name,"Профессионал"); //вызов конструктора суппер класса
     }

     public double Catch_Luck(){ //переопределение абстрактного метода
         super.Catch = (this.MaxCatch * (0.5 + super.genLuck()));
         return super.Catch;
     }
}

//-------------------
class Poacher extends Fisher
{
     private static double MaxCatch=400;

     public Poacher (String Name)
     {
       super(Name,"Браконьер"); //вызов конструктора суппер класса
     }

     public double Catch_Luck(){ //переопределение абстрактного метода
         super.Catch = (1 - 0.4 * super.genLuck());
         if(super.Catch < 0.9)
         {
             return 0;
         }
         else  return MaxCatch;
     }
}

//-------------------
public class  Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

          double catch_sum=0;
          double catch_tmp=0;

      System.out.print("\t***Welcome to fish***\n");


          Fisher arr[] = new Fisher[3];


          arr[0] = new Amateur("Берлиоз М.А.");
          arr[1] = new Profi("Воланд");
          arr[2] = new Poacher("Бездомный И.Н.");

          
          
          for(int j=0; j<3; j++)
          {
              
              for(int i=0; i<5; i++)
              {
                 catch_tmp = arr[j].Catch_Luck();
                 catch_sum += catch_tmp;

                 System.out.println("Рыбалка ["+i+"]"+"Статус - "+arr[j].get_FisherClass() + ", Ф.И.О - " + arr[j].get_Name()+", Улов = "+catch_tmp);
                 
              }
              System.out.println("Суммарный улов =="+catch_sum);
              catch_sum=0;
          
              System.out.println("\n");
              
          }

    }

}


В момент вызова методов
Код

arr[j].Catch_Luck()
arr[j].get_FisherClass() 
arr[j].get_Name()

происходит так называемое позденее связываение, которое удовлетворяет концепцию полиморфизма.

Всё ли верно? дополните/подправьте...

Спасибо за внимание.




Это сообщение отредактировал(а) initmax - 6.10.2009, 16:03
PM MAIL   Вверх
revenforv
Дата 6.10.2009, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 6.8.2009
Где: Санкт-Петербург

Репутация: нет
Всего: нет



Можно дополнить еще, что "позднее" связывание также называется динамическим.

В этой теме я уже разъяснял то, как это происходит (согласно спецификации языка Java). Буду рад, если она как-то дополнит ответ на поставленный вопрос..
PM MAIL Skype   Вверх
initmax
Дата 7.10.2009, 08:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 24.7.2009

Репутация: нет
Всего: нет



Спасибо!
Интересно "ранее связывание" в java существует?

Это сообщение отредактировал(а) initmax - 7.10.2009, 08:50
PM MAIL   Вверх
mbasil
Дата 7.10.2009, 09:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 399
Регистрация: 4.5.2007
Где: Москва

Репутация: 2
Всего: 13



Существует, для static и final методов.
PM MAIL   Вверх
ValerStrim
Дата 20.10.2010, 23:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



Я новичок и пытаюсь разобраться в перегрузках методов класса 
Допустим есть класс X b childX наследущий его методы...
Код:


Код

class X
  {
    public int sum(int a, int b)
    {
      return a + b;
    }
  }
 
  public class ChildX extends X
  {
    public long sum(int a, int b)
    {
      return (long)(a + b);
    }
  }



Какие из нижеприведенных перегрузок я могу юзать и это будет правильно:
public int sum(int a, long b){return 0;}
public long Sum(int a, int b){return 0;}
public int sum(int b, int a){return 0;}
public void sum(float x, float z){}
public abstract void sum(){}
Идея в том чтобы метод sum() мог возвращать значения как типа int, так и long 
Чёт не получается, помгите, разьясните, что можно, что нельзя (((
Заранее благодарю! 
PM MAIL   Вверх
Skipy
Дата 21.10.2010, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 6
Всего: 16



Цитата(ValerStrim @ 20.10.2010,  23:15)
Идея в том чтобы метод sum() мог возвращать значения как типа int, так и long 
Чёт не получается, помгите, разьясните, что можно, что нельзя (((

Ок, будем рассуждать логически. Пусть у Вас есть два метода:

Код
public int sum(int a, int b){
    return a + b;
}
public long sum(int a, int b){
    return (long)(a + b);
}


Ответьте на простой вопрос. Какой метод будет вызван в этом случае:

Код
sum(1,2);


P.S. Я имею полное право вызвать метод, не используя возвращаемого значения.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
ValerStrim
  Дата 21.10.2010, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 20.10.2010

Репутация: нет
Всего: нет



в соседней теме объяснили, да и сам вижу что ошибка на начальном этапе.
вопрос решён.

Это сообщение отредактировал(а) ValerStrim - 21.10.2010, 18:37
PM MAIL   Вверх
danilka
Дата 22.10.2010, 13:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.1.2010

Репутация: нет
Всего: нет



Цитата(mbasil @  5.10.2009,  19:23 Найти цитируемый пост)
ЗАМЕЧАНИЕ: В полиморфных методах, в их "подписях",  могут несколько отличаться только модификатор доступа и выбрасываемые исключения.


Начиная с 5-й джавы в перегруженном методе возвращаемым объектом может быть не только объект класса родительского метода но и его потомок.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0577 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.