2017-02-11 53 views
4

Итак, я пишу код, который включает в себя расширение класса, который я ранее написал, в котором файлы создаются именовались с использованием конструктора, который принимает имя и размер типа длинный. В этом исходном классе я проверил внутри конструктора, что введенное имя файла содержит один «.». но не требует определенного расширения в файле. Для этого нового класса, который я пишу, мне требуется расширение имени «.mp3». Однако мой компилятор не любит проверку перед супер-конструктором.Проверка правильности переменной перед вызовом суперструктора

Это мой текущий код:

public class Song extends DigitalMedia{ 

private String artist; 
private String album; 
private String name; 
private long size; 

public Song(String aName, long aSize, String aArtist, String aAlbum){ 
    super(aName, aSize); 
    setArtist(aArtist); 
    setAlbum(aAlbum); 
} 

Есть ли способ, чтобы проверить, что «aName» содержит».mp3" , прежде чем создать этот конструктор?

+0

@J Zane Я предлагаю вам изучить иерархию вызовов конструктора и понять, почему она сконструирована таким образом, что сначала необходимо вызвать суперкласс класса. Когда мы учимся, мы не должны просто переваривать факты, но должны попытаться найти ответ, как именно так, что случилось бы, если бы это было не так. Также я предлагаю вам изучить, что произойдет, если исключение будет отправлено из конструктора. Я попытался немного рассказать об этом в своем ответе, http://stackoverflow.com/a/42179930/504133 –

ответ

3

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

public Song(String aName, long aSize, String aArtist, String aAlbum){ 
    super(validateName(aName), aSize); 
    setArtist(aArtist); 
    setAlbum(aAlbum); 
} 

private static String validateName(String name) { 
    if (whatever) { 
     throw new Whatever(); 
    } 
    return name; 
} 
1

Альтернативным решением было бы применять свои правила с помощью встроенная проверка типов.

Вы можете создать MediaFormat:

interface MediaFormat { } 

MusicFormat, который реализует MediaFormat, что позволяет определить, какие музыкальные форматы:

enum MusicFormat implements MediaFormat { 
    MP3("mp3"); 

    private final String format; 

    MusicFormat(String format) { 
     this.format = format; 
    } 

    @Override 
    public String toString() { 
     return format; 
    } 
} 

DigitalMedia затем может быть составлен из MediaFormat:

class DigitalMedia { 
    private final MediaFormat format; 
    private final String name; 

    public DigitalMedia(String name, MediaFormat format) { 
     this.name = name; 
     this.format = format; 
    } 
} 

Song может согласиться с MusicFormat:

class Song { 
    public Song(String name, MusicFormat format) { 
     super(name, format); 
    } 
} 

Это заставит пользователь использовать все, что указано в MusicFormat, избегая все эти неприятные проверки. Затем вы можете открыть метод String, который возвращает name + "." + format

+0

Я думаю, что это лучшая альтернатива. Сильная типизация дает вам возможность решать ошибки во время компиляции, тогда как другие решения требуют обработки ошибок во время выполнения, что часто бывает сложнее и делает код более сложным. Конечно, если 'MusicFormat' создается из строки, вам также нужна обработка ошибок во время выполнения, но это решение позволяет отделить эту проблему от создания песен. –

+0

@MickMnemonic Это постоянный, никаких проверок времени выполнения не требуется. Единственная проблема заключалась бы в том, что он неверно объявлял константу, проверка которой не поможет. Не могли бы вы уточнить? –

+1

Похоже, что OP получает расширение файла как вход откуда-то, поэтому 'MusicFormat.valueOf (inputString)' нужно будет обрабатывать во время выполнения. –

0

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

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

public class Song extends DigitalMedia { 

    private String artist; 
    private String album; 
    private String name; 
    private long size; 

    private Song(String aName, long aSize, String aArtist, String aAlbum) { 
     super(aName, aSize); 
     setArtist(aArtist); 
     setAlbum(aAlbum); 
    } 

    public static Song makeSong(String aName, long aSize, String aArtist, String aAlbum) { 
     //... validation code 
     return new Song(aName, aSize, aArtist, aAlbum); 
    } 
    ... 
} 

Вместо ограничения самого типа вы используете инкапсуляцию для принудительного применения инварианта.

2

Выполнение кода, достигающего constructor, подразумевает, что объект находится в прямом эфире и теперь готов к инициализации его states (поля).

Объект класса A.java также может быть назван объектом класса Super A.java. Перед тем как класс A.java инициализирует состояние, его смысл в том, что объекты наследуют свойства и функции суперкласса. После того, как суперкласс выполнит инициализацию, класс A.java получает возможность выполнить инициализацию.

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

Что вы хотите сделать, если состояние не работает в constructor? У вас есть возможность выбросить исключение, но все же объект создан, вы можете проверить его, переопределив метод finalize() и проверив объект this. Вы можете захотеть повлиять на сборщик мусора, вызвав System.gc() для выполнения кода, достигнув метода finalize() раньше.

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

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

  • Нет связанных вопросов^_^